xref: /openbmc/linux/drivers/pci/hotplug/shpchp_hpc.c (revision 9676f406)
1736759efSBjorn Helgaas // SPDX-License-Identifier: GPL-2.0+
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * Standard PCI Hot Plug Driver
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Copyright (C) 1995,2001 Compaq Computer Corporation
61da177e4SLinus Torvalds  * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
71da177e4SLinus Torvalds  * Copyright (C) 2001 IBM Corp.
81da177e4SLinus Torvalds  * Copyright (C) 2003-2004 Intel Corporation
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  * All rights reserved.
111da177e4SLinus Torvalds  *
128cf4c195SKristen Accardi  * Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com>
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  */
151da177e4SLinus Torvalds 
161da177e4SLinus Torvalds #include <linux/kernel.h>
171da177e4SLinus Torvalds #include <linux/module.h>
181da177e4SLinus Torvalds #include <linux/types.h>
191da177e4SLinus Torvalds #include <linux/pci.h>
20d4d28dd4SAndrew Morton #include <linux/interrupt.h>
21d4d28dd4SAndrew Morton 
221da177e4SLinus Torvalds #include "shpchp.h"
231da177e4SLinus Torvalds 
241da177e4SLinus Torvalds /* Slot Available Register I field definition */
251da177e4SLinus Torvalds #define SLOT_33MHZ		0x0000001f
261da177e4SLinus Torvalds #define SLOT_66MHZ_PCIX		0x00001f00
271da177e4SLinus Torvalds #define SLOT_100MHZ_PCIX	0x001f0000
281da177e4SLinus Torvalds #define SLOT_133MHZ_PCIX	0x1f000000
291da177e4SLinus Torvalds 
301da177e4SLinus Torvalds /* Slot Available Register II field definition */
311da177e4SLinus Torvalds #define SLOT_66MHZ		0x0000001f
321da177e4SLinus Torvalds #define SLOT_66MHZ_PCIX_266	0x00000f00
331da177e4SLinus Torvalds #define SLOT_100MHZ_PCIX_266	0x0000f000
341da177e4SLinus Torvalds #define SLOT_133MHZ_PCIX_266	0x000f0000
351da177e4SLinus Torvalds #define SLOT_66MHZ_PCIX_533	0x00f00000
361da177e4SLinus Torvalds #define SLOT_100MHZ_PCIX_533	0x0f000000
371da177e4SLinus Torvalds #define SLOT_133MHZ_PCIX_533	0xf0000000
381da177e4SLinus Torvalds 
391da177e4SLinus Torvalds /* Slot Configuration */
401da177e4SLinus Torvalds #define SLOT_NUM		0x0000001F
411da177e4SLinus Torvalds #define	FIRST_DEV_NUM		0x00001F00
421da177e4SLinus Torvalds #define PSN			0x07FF0000
431da177e4SLinus Torvalds #define	UPDOWN			0x20000000
441da177e4SLinus Torvalds #define	MRLSENSOR		0x40000000
451da177e4SLinus Torvalds #define ATTN_BUTTON		0x80000000
461da177e4SLinus Torvalds 
472b34da7eSKenji Kaneshige /*
48c4cecc19SKenji Kaneshige  * Interrupt Locator Register definitions
49c4cecc19SKenji Kaneshige  */
50c4cecc19SKenji Kaneshige #define CMD_INTR_PENDING	(1 << 0)
51c4cecc19SKenji Kaneshige #define SLOT_INTR_PENDING(i)	(1 << (i + 1))
52c4cecc19SKenji Kaneshige 
53c4cecc19SKenji Kaneshige /*
54e7138723SKenji Kaneshige  * Controller SERR-INT Register
55e7138723SKenji Kaneshige  */
56e7138723SKenji Kaneshige #define GLOBAL_INTR_MASK	(1 << 0)
57e7138723SKenji Kaneshige #define GLOBAL_SERR_MASK	(1 << 1)
58e7138723SKenji Kaneshige #define COMMAND_INTR_MASK	(1 << 2)
59e7138723SKenji Kaneshige #define ARBITER_SERR_MASK	(1 << 3)
60e7138723SKenji Kaneshige #define COMMAND_DETECTED	(1 << 16)
61e7138723SKenji Kaneshige #define ARBITER_DETECTED	(1 << 17)
62e7138723SKenji Kaneshige #define SERR_INTR_RSVDZ_MASK	0xfffc0000
63e7138723SKenji Kaneshige 
64e7138723SKenji Kaneshige /*
652b34da7eSKenji Kaneshige  * Logical Slot Register definitions
662b34da7eSKenji Kaneshige  */
672b34da7eSKenji Kaneshige #define SLOT_REG(i)		(SLOT1 + (4 * i))
682b34da7eSKenji Kaneshige 
695858759cSKenji Kaneshige #define SLOT_STATE_SHIFT	(0)
705858759cSKenji Kaneshige #define SLOT_STATE_MASK		(3 << 0)
715858759cSKenji Kaneshige #define SLOT_STATE_PWRONLY	(1)
725858759cSKenji Kaneshige #define SLOT_STATE_ENABLED	(2)
735858759cSKenji Kaneshige #define SLOT_STATE_DISABLED	(3)
745858759cSKenji Kaneshige #define PWR_LED_STATE_SHIFT	(2)
755858759cSKenji Kaneshige #define PWR_LED_STATE_MASK	(3 << 2)
765858759cSKenji Kaneshige #define ATN_LED_STATE_SHIFT	(4)
775858759cSKenji Kaneshige #define ATN_LED_STATE_MASK	(3 << 4)
785858759cSKenji Kaneshige #define ATN_LED_STATE_ON	(1)
795858759cSKenji Kaneshige #define ATN_LED_STATE_BLINK	(2)
805858759cSKenji Kaneshige #define ATN_LED_STATE_OFF	(3)
815858759cSKenji Kaneshige #define POWER_FAULT		(1 << 6)
825858759cSKenji Kaneshige #define ATN_BUTTON		(1 << 7)
835858759cSKenji Kaneshige #define MRL_SENSOR		(1 << 8)
845858759cSKenji Kaneshige #define MHZ66_CAP		(1 << 9)
855858759cSKenji Kaneshige #define PRSNT_SHIFT		(10)
865858759cSKenji Kaneshige #define PRSNT_MASK		(3 << 10)
875858759cSKenji Kaneshige #define PCIX_CAP_SHIFT		(12)
885858759cSKenji Kaneshige #define PCIX_CAP_MASK_PI1	(3 << 12)
895858759cSKenji Kaneshige #define PCIX_CAP_MASK_PI2	(7 << 12)
905858759cSKenji Kaneshige #define PRSNT_CHANGE_DETECTED	(1 << 16)
915858759cSKenji Kaneshige #define ISO_PFAULT_DETECTED	(1 << 17)
925858759cSKenji Kaneshige #define BUTTON_PRESS_DETECTED	(1 << 18)
935858759cSKenji Kaneshige #define MRL_CHANGE_DETECTED	(1 << 19)
945858759cSKenji Kaneshige #define CON_PFAULT_DETECTED	(1 << 20)
955858759cSKenji Kaneshige #define PRSNT_CHANGE_INTR_MASK	(1 << 24)
965858759cSKenji Kaneshige #define ISO_PFAULT_INTR_MASK	(1 << 25)
975858759cSKenji Kaneshige #define BUTTON_PRESS_INTR_MASK	(1 << 26)
985858759cSKenji Kaneshige #define MRL_CHANGE_INTR_MASK	(1 << 27)
995858759cSKenji Kaneshige #define CON_PFAULT_INTR_MASK	(1 << 28)
1005858759cSKenji Kaneshige #define MRL_CHANGE_SERR_MASK	(1 << 29)
1015858759cSKenji Kaneshige #define CON_PFAULT_SERR_MASK	(1 << 30)
1023b8fdb75SDan Carpenter #define SLOT_REG_RSVDZ_MASK	((1 << 15) | (7 << 21))
1031da177e4SLinus Torvalds 
1044085399dSKenji Kaneshige /*
105f7625980SBjorn Helgaas  * SHPC Command Code definitions
1064085399dSKenji Kaneshige  *
1074085399dSKenji Kaneshige  *     Slot Operation				00h - 3Fh
1084085399dSKenji Kaneshige  *     Set Bus Segment Speed/Mode A		40h - 47h
1094085399dSKenji Kaneshige  *     Power-Only All Slots			48h
1104085399dSKenji Kaneshige  *     Enable All Slots				49h
1114085399dSKenji Kaneshige  *     Set Bus Segment Speed/Mode B (PI=2)	50h - 5Fh
1124085399dSKenji Kaneshige  *     Reserved Command Codes			60h - BFh
1134085399dSKenji Kaneshige  *     Vendor Specific Commands			C0h - FFh
1144085399dSKenji Kaneshige  */
1154085399dSKenji Kaneshige #define SET_SLOT_PWR		0x01	/* Slot Operation */
1161da177e4SLinus Torvalds #define SET_SLOT_ENABLE		0x02
1171da177e4SLinus Torvalds #define SET_SLOT_DISABLE	0x03
1181da177e4SLinus Torvalds #define SET_PWR_ON		0x04
1191da177e4SLinus Torvalds #define SET_PWR_BLINK		0x08
1204085399dSKenji Kaneshige #define SET_PWR_OFF		0x0c
1214085399dSKenji Kaneshige #define SET_ATTN_ON		0x10
1224085399dSKenji Kaneshige #define SET_ATTN_BLINK		0x20
1234085399dSKenji Kaneshige #define SET_ATTN_OFF		0x30
1244085399dSKenji Kaneshige #define SETA_PCI_33MHZ		0x40	/* Set Bus Segment Speed/Mode A */
1251da177e4SLinus Torvalds #define SETA_PCI_66MHZ		0x41
1261da177e4SLinus Torvalds #define SETA_PCIX_66MHZ		0x42
1271da177e4SLinus Torvalds #define SETA_PCIX_100MHZ	0x43
1281da177e4SLinus Torvalds #define SETA_PCIX_133MHZ	0x44
1294085399dSKenji Kaneshige #define SETA_RESERVED1		0x45
1304085399dSKenji Kaneshige #define SETA_RESERVED2		0x46
1314085399dSKenji Kaneshige #define SETA_RESERVED3		0x47
1324085399dSKenji Kaneshige #define SET_PWR_ONLY_ALL	0x48	/* Power-Only All Slots */
1334085399dSKenji Kaneshige #define SET_ENABLE_ALL		0x49	/* Enable All Slots */
1344085399dSKenji Kaneshige #define	SETB_PCI_33MHZ		0x50	/* Set Bus Segment Speed/Mode B */
1351da177e4SLinus Torvalds #define SETB_PCI_66MHZ		0x51
1361da177e4SLinus Torvalds #define SETB_PCIX_66MHZ_PM	0x52
1371da177e4SLinus Torvalds #define SETB_PCIX_100MHZ_PM	0x53
1381da177e4SLinus Torvalds #define SETB_PCIX_133MHZ_PM	0x54
1391da177e4SLinus Torvalds #define SETB_PCIX_66MHZ_EM	0x55
1401da177e4SLinus Torvalds #define SETB_PCIX_100MHZ_EM	0x56
1411da177e4SLinus Torvalds #define SETB_PCIX_133MHZ_EM	0x57
1421da177e4SLinus Torvalds #define SETB_PCIX_66MHZ_266	0x58
1431da177e4SLinus Torvalds #define SETB_PCIX_100MHZ_266	0x59
1441da177e4SLinus Torvalds #define SETB_PCIX_133MHZ_266	0x5a
1451da177e4SLinus Torvalds #define SETB_PCIX_66MHZ_533	0x5b
1461da177e4SLinus Torvalds #define SETB_PCIX_100MHZ_533	0x5c
1471da177e4SLinus Torvalds #define SETB_PCIX_133MHZ_533	0x5d
1484085399dSKenji Kaneshige #define SETB_RESERVED1		0x5e
1494085399dSKenji Kaneshige #define SETB_RESERVED2		0x5f
1501da177e4SLinus Torvalds 
1514085399dSKenji Kaneshige /*
1524085399dSKenji Kaneshige  * SHPC controller command error code
1534085399dSKenji Kaneshige  */
1541da177e4SLinus Torvalds #define SWITCH_OPEN		0x1
1551da177e4SLinus Torvalds #define INVALID_CMD		0x2
1561da177e4SLinus Torvalds #define INVALID_SPEED_MODE	0x4
1571da177e4SLinus Torvalds 
1584085399dSKenji Kaneshige /*
1594085399dSKenji Kaneshige  * For accessing SHPC Working Register Set via PCI Configuration Space
1604085399dSKenji Kaneshige  */
1611da177e4SLinus Torvalds #define DWORD_SELECT		0x2
1621da177e4SLinus Torvalds #define DWORD_DATA		0x4
1631da177e4SLinus Torvalds 
1641da177e4SLinus Torvalds /* Field Offset in Logical Slot Register - byte boundary */
1651da177e4SLinus Torvalds #define SLOT_EVENT_LATCH	0x2
1661da177e4SLinus Torvalds #define SLOT_SERR_INT_MASK	0x3
1671da177e4SLinus Torvalds 
1687d12e780SDavid Howells static irqreturn_t shpc_isr(int irq, void *dev_id);
1690abe68ceSKenji Kaneshige static void start_int_poll_timer(struct controller *ctrl, int sec);
170d29aaddaSKenji Kaneshige static int hpc_check_cmd_status(struct controller *ctrl);
1711da177e4SLinus Torvalds 
shpc_readb(struct controller * ctrl,int reg)17275d97c59SKenji Kaneshige static inline u8 shpc_readb(struct controller *ctrl, int reg)
17375d97c59SKenji Kaneshige {
1740abe68ceSKenji Kaneshige 	return readb(ctrl->creg + reg);
17575d97c59SKenji Kaneshige }
17675d97c59SKenji Kaneshige 
shpc_readw(struct controller * ctrl,int reg)17775d97c59SKenji Kaneshige static inline u16 shpc_readw(struct controller *ctrl, int reg)
17875d97c59SKenji Kaneshige {
1790abe68ceSKenji Kaneshige 	return readw(ctrl->creg + reg);
18075d97c59SKenji Kaneshige }
18175d97c59SKenji Kaneshige 
shpc_writew(struct controller * ctrl,int reg,u16 val)18275d97c59SKenji Kaneshige static inline void shpc_writew(struct controller *ctrl, int reg, u16 val)
18375d97c59SKenji Kaneshige {
1840abe68ceSKenji Kaneshige 	writew(val, ctrl->creg + reg);
18575d97c59SKenji Kaneshige }
18675d97c59SKenji Kaneshige 
shpc_readl(struct controller * ctrl,int reg)18775d97c59SKenji Kaneshige static inline u32 shpc_readl(struct controller *ctrl, int reg)
18875d97c59SKenji Kaneshige {
1890abe68ceSKenji Kaneshige 	return readl(ctrl->creg + reg);
19075d97c59SKenji Kaneshige }
19175d97c59SKenji Kaneshige 
shpc_writel(struct controller * ctrl,int reg,u32 val)19275d97c59SKenji Kaneshige static inline void shpc_writel(struct controller *ctrl, int reg, u32 val)
19375d97c59SKenji Kaneshige {
1940abe68ceSKenji Kaneshige 	writel(val, ctrl->creg + reg);
19575d97c59SKenji Kaneshige }
19675d97c59SKenji Kaneshige 
shpc_indirect_read(struct controller * ctrl,int index,u32 * value)19775d97c59SKenji Kaneshige static inline int shpc_indirect_read(struct controller *ctrl, int index,
19875d97c59SKenji Kaneshige 				     u32 *value)
19975d97c59SKenji Kaneshige {
20075d97c59SKenji Kaneshige 	int rc;
20175d97c59SKenji Kaneshige 	u32 cap_offset = ctrl->cap_offset;
20275d97c59SKenji Kaneshige 	struct pci_dev *pdev = ctrl->pci_dev;
20375d97c59SKenji Kaneshige 
20475d97c59SKenji Kaneshige 	rc = pci_write_config_byte(pdev, cap_offset + DWORD_SELECT, index);
20575d97c59SKenji Kaneshige 	if (rc)
20675d97c59SKenji Kaneshige 		return rc;
20775d97c59SKenji Kaneshige 	return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value);
20875d97c59SKenji Kaneshige }
20975d97c59SKenji Kaneshige 
210f4263957SKenji Kaneshige /*
211f4263957SKenji Kaneshige  * This is the interrupt polling timeout function.
212f4263957SKenji Kaneshige  */
int_poll_timeout(struct timer_list * t)2133691314aSKees Cook static void int_poll_timeout(struct timer_list *t)
2141da177e4SLinus Torvalds {
2153691314aSKees Cook 	struct controller *ctrl = from_timer(ctrl, t, poll_timer);
2161da177e4SLinus Torvalds 
2171da177e4SLinus Torvalds 	/* Poll for interrupt events.  regs == NULL => polling */
2180abe68ceSKenji Kaneshige 	shpc_isr(0, ctrl);
2191da177e4SLinus Torvalds 
2201da177e4SLinus Torvalds 	if (!shpchp_poll_time)
221f4263957SKenji Kaneshige 		shpchp_poll_time = 2; /* default polling interval is 2 sec */
2221da177e4SLinus Torvalds 
2230abe68ceSKenji Kaneshige 	start_int_poll_timer(ctrl, shpchp_poll_time);
2241da177e4SLinus Torvalds }
2251da177e4SLinus Torvalds 
226f4263957SKenji Kaneshige /*
227f4263957SKenji Kaneshige  * This function starts the interrupt polling timer.
228f4263957SKenji Kaneshige  */
start_int_poll_timer(struct controller * ctrl,int sec)2290abe68ceSKenji Kaneshige static void start_int_poll_timer(struct controller *ctrl, int sec)
2301da177e4SLinus Torvalds {
231f4263957SKenji Kaneshige 	/* Clamp to sane value */
232f4263957SKenji Kaneshige 	if ((sec <= 0) || (sec > 60))
233f4263957SKenji Kaneshige 		sec = 2;
2341da177e4SLinus Torvalds 
2350abe68ceSKenji Kaneshige 	ctrl->poll_timer.expires = jiffies + sec * HZ;
2360abe68ceSKenji Kaneshige 	add_timer(&ctrl->poll_timer);
2371da177e4SLinus Torvalds }
2381da177e4SLinus Torvalds 
is_ctrl_busy(struct controller * ctrl)239d1729cceSKenji Kaneshige static inline int is_ctrl_busy(struct controller *ctrl)
240d1729cceSKenji Kaneshige {
241d1729cceSKenji Kaneshige 	u16 cmd_status = shpc_readw(ctrl, CMD_STATUS);
242d1729cceSKenji Kaneshige 	return cmd_status & 0x1;
243d1729cceSKenji Kaneshige }
244d1729cceSKenji Kaneshige 
245b4a1efffSKenji Kaneshige /*
246b4a1efffSKenji Kaneshige  * Returns 1 if SHPC finishes executing a command within 1 sec,
247b4a1efffSKenji Kaneshige  * otherwise returns 0.
248b4a1efffSKenji Kaneshige  */
shpc_poll_ctrl_busy(struct controller * ctrl)249b4a1efffSKenji Kaneshige static inline int shpc_poll_ctrl_busy(struct controller *ctrl)
250b4a1efffSKenji Kaneshige {
251b4a1efffSKenji Kaneshige 	int i;
252b4a1efffSKenji Kaneshige 
253d1729cceSKenji Kaneshige 	if (!is_ctrl_busy(ctrl))
254b4a1efffSKenji Kaneshige 		return 1;
255b4a1efffSKenji Kaneshige 
256b4a1efffSKenji Kaneshige 	/* Check every 0.1 sec for a total of 1 sec */
257b4a1efffSKenji Kaneshige 	for (i = 0; i < 10; i++) {
258b4a1efffSKenji Kaneshige 		msleep(100);
259d1729cceSKenji Kaneshige 		if (!is_ctrl_busy(ctrl))
260b4a1efffSKenji Kaneshige 			return 1;
261b4a1efffSKenji Kaneshige 	}
262b4a1efffSKenji Kaneshige 
263b4a1efffSKenji Kaneshige 	return 0;
264b4a1efffSKenji Kaneshige }
265b4a1efffSKenji Kaneshige 
shpc_wait_cmd(struct controller * ctrl)266bd62e271SKenji Kaneshige static inline int shpc_wait_cmd(struct controller *ctrl)
267bd62e271SKenji Kaneshige {
268bd62e271SKenji Kaneshige 	int retval = 0;
269b4a1efffSKenji Kaneshige 	unsigned long timeout = msecs_to_jiffies(1000);
270b4a1efffSKenji Kaneshige 	int rc;
271b4a1efffSKenji Kaneshige 
272b4a1efffSKenji Kaneshige 	if (shpchp_poll_mode)
273b4a1efffSKenji Kaneshige 		rc = shpc_poll_ctrl_busy(ctrl);
274b4a1efffSKenji Kaneshige 	else
275b4a1efffSKenji Kaneshige 		rc = wait_event_interruptible_timeout(ctrl->queue,
2766aa562c2SKenji Kaneshige 						!is_ctrl_busy(ctrl), timeout);
277d1729cceSKenji Kaneshige 	if (!rc && is_ctrl_busy(ctrl)) {
278bd62e271SKenji Kaneshige 		retval = -EIO;
279f98ca311STaku Izumi 		ctrl_err(ctrl, "Command not completed in 1000 msec\n");
280bd62e271SKenji Kaneshige 	} else if (rc < 0) {
281bd62e271SKenji Kaneshige 		retval = -EINTR;
282f98ca311STaku Izumi 		ctrl_info(ctrl, "Command was interrupted by a signal\n");
283bd62e271SKenji Kaneshige 	}
284bd62e271SKenji Kaneshige 
285bd62e271SKenji Kaneshige 	return retval;
286bd62e271SKenji Kaneshige }
287bd62e271SKenji Kaneshige 
shpc_write_cmd(struct slot * slot,u8 t_slot,u8 cmd)2881da177e4SLinus Torvalds static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
2891da177e4SLinus Torvalds {
29075d97c59SKenji Kaneshige 	struct controller *ctrl = slot->ctrl;
2911da177e4SLinus Torvalds 	u16 cmd_status;
2921da177e4SLinus Torvalds 	int retval = 0;
2931da177e4SLinus Torvalds 	u16 temp_word;
2941da177e4SLinus Torvalds 
295d29aaddaSKenji Kaneshige 	mutex_lock(&slot->ctrl->cmd_lock);
296d29aaddaSKenji Kaneshige 
297b4a1efffSKenji Kaneshige 	if (!shpc_poll_ctrl_busy(ctrl)) {
298*b2105b9fSKrzysztof Wilczyński 		/* After 1 sec and the controller is still busy */
299be7bce25STaku Izumi 		ctrl_err(ctrl, "Controller is still busy after 1 sec\n");
300d29aaddaSKenji Kaneshige 		retval = -EBUSY;
301d29aaddaSKenji Kaneshige 		goto out;
3021da177e4SLinus Torvalds 	}
3031da177e4SLinus Torvalds 
3041da177e4SLinus Torvalds 	++t_slot;
3051da177e4SLinus Torvalds 	temp_word =  (t_slot << 8) | (cmd & 0xFF);
306f98ca311STaku Izumi 	ctrl_dbg(ctrl, "%s: t_slot %x cmd %x\n", __func__, t_slot, cmd);
3071da177e4SLinus Torvalds 
3081da177e4SLinus Torvalds 	/* To make sure the Controller Busy bit is 0 before we send out the
3091da177e4SLinus Torvalds 	 * command.
3101da177e4SLinus Torvalds 	 */
31175d97c59SKenji Kaneshige 	shpc_writew(ctrl, CMD, temp_word);
3121da177e4SLinus Torvalds 
313bd62e271SKenji Kaneshige 	/*
314bd62e271SKenji Kaneshige 	 * Wait for command completion.
315bd62e271SKenji Kaneshige 	 */
316bd62e271SKenji Kaneshige 	retval = shpc_wait_cmd(slot->ctrl);
317d29aaddaSKenji Kaneshige 	if (retval)
318d29aaddaSKenji Kaneshige 		goto out;
319d29aaddaSKenji Kaneshige 
320d29aaddaSKenji Kaneshige 	cmd_status = hpc_check_cmd_status(slot->ctrl);
321d29aaddaSKenji Kaneshige 	if (cmd_status) {
322227f0647SRyan Desfosses 		ctrl_err(ctrl, "Failed to issued command 0x%x (error code = %d)\n",
323be7bce25STaku Izumi 			 cmd, cmd_status);
324d29aaddaSKenji Kaneshige 		retval = -EIO;
325d29aaddaSKenji Kaneshige 	}
326d29aaddaSKenji Kaneshige  out:
327d29aaddaSKenji Kaneshige 	mutex_unlock(&slot->ctrl->cmd_lock);
3281da177e4SLinus Torvalds 	return retval;
3291da177e4SLinus Torvalds }
3301da177e4SLinus Torvalds 
hpc_check_cmd_status(struct controller * ctrl)3311da177e4SLinus Torvalds static int hpc_check_cmd_status(struct controller *ctrl)
3321da177e4SLinus Torvalds {
3331da177e4SLinus Torvalds 	int retval = 0;
3341555b33dSKenji Kaneshige 	u16 cmd_status = shpc_readw(ctrl, CMD_STATUS) & 0x000F;
3351da177e4SLinus Torvalds 
3361da177e4SLinus Torvalds 	switch (cmd_status >> 1) {
3371da177e4SLinus Torvalds 	case 0:
3381da177e4SLinus Torvalds 		retval = 0;
3391da177e4SLinus Torvalds 		break;
3401da177e4SLinus Torvalds 	case 1:
3411da177e4SLinus Torvalds 		retval = SWITCH_OPEN;
342be7bce25STaku Izumi 		ctrl_err(ctrl, "Switch opened!\n");
3431da177e4SLinus Torvalds 		break;
3441da177e4SLinus Torvalds 	case 2:
3451da177e4SLinus Torvalds 		retval = INVALID_CMD;
346be7bce25STaku Izumi 		ctrl_err(ctrl, "Invalid HPC command!\n");
3471da177e4SLinus Torvalds 		break;
3481da177e4SLinus Torvalds 	case 4:
3491da177e4SLinus Torvalds 		retval = INVALID_SPEED_MODE;
350be7bce25STaku Izumi 		ctrl_err(ctrl, "Invalid bus speed/mode!\n");
3511da177e4SLinus Torvalds 		break;
3521da177e4SLinus Torvalds 	default:
3531da177e4SLinus Torvalds 		retval = cmd_status;
3541da177e4SLinus Torvalds 	}
3551da177e4SLinus Torvalds 
3561da177e4SLinus Torvalds 	return retval;
3571da177e4SLinus Torvalds }
3581da177e4SLinus Torvalds 
3591da177e4SLinus Torvalds 
hpc_get_attention_status(struct slot * slot,u8 * status)3601da177e4SLinus Torvalds static int hpc_get_attention_status(struct slot *slot, u8 *status)
3611da177e4SLinus Torvalds {
36275d97c59SKenji Kaneshige 	struct controller *ctrl = slot->ctrl;
3631555b33dSKenji Kaneshige 	u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
3641555b33dSKenji Kaneshige 	u8 state = (slot_reg & ATN_LED_STATE_MASK) >> ATN_LED_STATE_SHIFT;
3651da177e4SLinus Torvalds 
3665858759cSKenji Kaneshige 	switch (state) {
3675858759cSKenji Kaneshige 	case ATN_LED_STATE_ON:
3681da177e4SLinus Torvalds 		*status = 1;	/* On */
3691da177e4SLinus Torvalds 		break;
3705858759cSKenji Kaneshige 	case ATN_LED_STATE_BLINK:
3711da177e4SLinus Torvalds 		*status = 2;	/* Blink */
3721da177e4SLinus Torvalds 		break;
3735858759cSKenji Kaneshige 	case ATN_LED_STATE_OFF:
3741da177e4SLinus Torvalds 		*status = 0;	/* Off */
3751da177e4SLinus Torvalds 		break;
3761da177e4SLinus Torvalds 	default:
3775858759cSKenji Kaneshige 		*status = 0xFF;	/* Reserved */
3781da177e4SLinus Torvalds 		break;
3791da177e4SLinus Torvalds 	}
3801da177e4SLinus Torvalds 
3811da177e4SLinus Torvalds 	return 0;
3821da177e4SLinus Torvalds }
3831da177e4SLinus Torvalds 
hpc_get_power_status(struct slot * slot,u8 * status)3841da177e4SLinus Torvalds static int hpc_get_power_status(struct slot *slot, u8 *status)
3851da177e4SLinus Torvalds {
38675d97c59SKenji Kaneshige 	struct controller *ctrl = slot->ctrl;
3871555b33dSKenji Kaneshige 	u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
3881555b33dSKenji Kaneshige 	u8 state = (slot_reg & SLOT_STATE_MASK) >> SLOT_STATE_SHIFT;
3891da177e4SLinus Torvalds 
3905858759cSKenji Kaneshige 	switch (state) {
3915858759cSKenji Kaneshige 	case SLOT_STATE_PWRONLY:
3921da177e4SLinus Torvalds 		*status = 2;	/* Powered only */
3931da177e4SLinus Torvalds 		break;
3945858759cSKenji Kaneshige 	case SLOT_STATE_ENABLED:
3951da177e4SLinus Torvalds 		*status = 1;	/* Enabled */
3961da177e4SLinus Torvalds 		break;
3975858759cSKenji Kaneshige 	case SLOT_STATE_DISABLED:
3981da177e4SLinus Torvalds 		*status = 0;	/* Disabled */
3991da177e4SLinus Torvalds 		break;
4001da177e4SLinus Torvalds 	default:
4015858759cSKenji Kaneshige 		*status = 0xFF;	/* Reserved */
4021da177e4SLinus Torvalds 		break;
4031da177e4SLinus Torvalds 	}
4041da177e4SLinus Torvalds 
4055858759cSKenji Kaneshige 	return 0;
4061da177e4SLinus Torvalds }
4071da177e4SLinus Torvalds 
4081da177e4SLinus Torvalds 
hpc_get_latch_status(struct slot * slot,u8 * status)4091da177e4SLinus Torvalds static int hpc_get_latch_status(struct slot *slot, u8 *status)
4101da177e4SLinus Torvalds {
41175d97c59SKenji Kaneshige 	struct controller *ctrl = slot->ctrl;
4121555b33dSKenji Kaneshige 	u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
4131da177e4SLinus Torvalds 
4145858759cSKenji Kaneshige 	*status = !!(slot_reg & MRL_SENSOR);	/* 0 -> close; 1 -> open */
4151da177e4SLinus Torvalds 
4161da177e4SLinus Torvalds 	return 0;
4171da177e4SLinus Torvalds }
4181da177e4SLinus Torvalds 
hpc_get_adapter_status(struct slot * slot,u8 * status)4191da177e4SLinus Torvalds static int hpc_get_adapter_status(struct slot *slot, u8 *status)
4201da177e4SLinus Torvalds {
42175d97c59SKenji Kaneshige 	struct controller *ctrl = slot->ctrl;
4221555b33dSKenji Kaneshige 	u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
4231555b33dSKenji Kaneshige 	u8 state = (slot_reg & PRSNT_MASK) >> PRSNT_SHIFT;
4241da177e4SLinus Torvalds 
4255858759cSKenji Kaneshige 	*status = (state != 0x3) ? 1 : 0;
4261da177e4SLinus Torvalds 
4271da177e4SLinus Torvalds 	return 0;
4281da177e4SLinus Torvalds }
4291da177e4SLinus Torvalds 
hpc_get_prog_int(struct slot * slot,u8 * prog_int)4301da177e4SLinus Torvalds static int hpc_get_prog_int(struct slot *slot, u8 *prog_int)
4311da177e4SLinus Torvalds {
43275d97c59SKenji Kaneshige 	struct controller *ctrl = slot->ctrl;
4331da177e4SLinus Torvalds 
43475d97c59SKenji Kaneshige 	*prog_int = shpc_readb(ctrl, PROG_INTERFACE);
4351da177e4SLinus Torvalds 
4361da177e4SLinus Torvalds 	return 0;
4371da177e4SLinus Torvalds }
4381da177e4SLinus Torvalds 
hpc_get_adapter_speed(struct slot * slot,enum pci_bus_speed * value)4391da177e4SLinus Torvalds static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
4401da177e4SLinus Torvalds {
4411da177e4SLinus Torvalds 	int retval = 0;
44275d97c59SKenji Kaneshige 	struct controller *ctrl = slot->ctrl;
4432b34da7eSKenji Kaneshige 	u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
4445858759cSKenji Kaneshige 	u8 m66_cap  = !!(slot_reg & MHZ66_CAP);
445795eb5c4SKenji Kaneshige 	u8 pi, pcix_cap;
4461da177e4SLinus Torvalds 
44779e50e72SQuentin Lambert 	retval = hpc_get_prog_int(slot, &pi);
44879e50e72SQuentin Lambert 	if (retval)
449795eb5c4SKenji Kaneshige 		return retval;
450795eb5c4SKenji Kaneshige 
451795eb5c4SKenji Kaneshige 	switch (pi) {
452795eb5c4SKenji Kaneshige 	case 1:
453795eb5c4SKenji Kaneshige 		pcix_cap = (slot_reg & PCIX_CAP_MASK_PI1) >> PCIX_CAP_SHIFT;
454795eb5c4SKenji Kaneshige 		break;
455795eb5c4SKenji Kaneshige 	case 2:
456795eb5c4SKenji Kaneshige 		pcix_cap = (slot_reg & PCIX_CAP_MASK_PI2) >> PCIX_CAP_SHIFT;
457795eb5c4SKenji Kaneshige 		break;
458795eb5c4SKenji Kaneshige 	default:
459795eb5c4SKenji Kaneshige 		return -ENODEV;
460795eb5c4SKenji Kaneshige 	}
461795eb5c4SKenji Kaneshige 
462f98ca311STaku Izumi 	ctrl_dbg(ctrl, "%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n",
46366bef8c0SHarvey Harrison 		 __func__, slot_reg, pcix_cap, m66_cap);
4641da177e4SLinus Torvalds 
4651da177e4SLinus Torvalds 	switch (pcix_cap) {
4660afabe90SKenji Kaneshige 	case 0x0:
4671da177e4SLinus Torvalds 		*value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
4681da177e4SLinus Torvalds 		break;
4690afabe90SKenji Kaneshige 	case 0x1:
4701da177e4SLinus Torvalds 		*value = PCI_SPEED_66MHz_PCIX;
4711da177e4SLinus Torvalds 		break;
4720afabe90SKenji Kaneshige 	case 0x3:
4731da177e4SLinus Torvalds 		*value = PCI_SPEED_133MHz_PCIX;
4741da177e4SLinus Torvalds 		break;
4750afabe90SKenji Kaneshige 	case 0x4:
4761da177e4SLinus Torvalds 		*value = PCI_SPEED_133MHz_PCIX_266;
4771da177e4SLinus Torvalds 		break;
4780afabe90SKenji Kaneshige 	case 0x5:
4791da177e4SLinus Torvalds 		*value = PCI_SPEED_133MHz_PCIX_533;
4801da177e4SLinus Torvalds 		break;
4810afabe90SKenji Kaneshige 	case 0x2:
4821da177e4SLinus Torvalds 	default:
4831da177e4SLinus Torvalds 		*value = PCI_SPEED_UNKNOWN;
4841da177e4SLinus Torvalds 		retval = -ENODEV;
4851da177e4SLinus Torvalds 		break;
4861da177e4SLinus Torvalds 	}
4871da177e4SLinus Torvalds 
488f98ca311STaku Izumi 	ctrl_dbg(ctrl, "Adapter speed = %d\n", *value);
4891da177e4SLinus Torvalds 	return retval;
4901da177e4SLinus Torvalds }
4911da177e4SLinus Torvalds 
hpc_query_power_fault(struct slot * slot)4921da177e4SLinus Torvalds static int hpc_query_power_fault(struct slot *slot)
4931da177e4SLinus Torvalds {
49475d97c59SKenji Kaneshige 	struct controller *ctrl = slot->ctrl;
4951555b33dSKenji Kaneshige 	u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
4961da177e4SLinus Torvalds 
4971da177e4SLinus Torvalds 	/* Note: Logic 0 => fault */
4985858759cSKenji Kaneshige 	return !(slot_reg & POWER_FAULT);
4991da177e4SLinus Torvalds }
5001da177e4SLinus Torvalds 
hpc_set_attention_status(struct slot * slot,u8 value)5011da177e4SLinus Torvalds static int hpc_set_attention_status(struct slot *slot, u8 value)
5021da177e4SLinus Torvalds {
5031da177e4SLinus Torvalds 	u8 slot_cmd = 0;
5041da177e4SLinus Torvalds 
5051da177e4SLinus Torvalds 	switch (value) {
5061da177e4SLinus Torvalds 		case 0:
5074085399dSKenji Kaneshige 			slot_cmd = SET_ATTN_OFF;	/* OFF */
5081da177e4SLinus Torvalds 			break;
5091da177e4SLinus Torvalds 		case 1:
5104085399dSKenji Kaneshige 			slot_cmd = SET_ATTN_ON;		/* ON */
5111da177e4SLinus Torvalds 			break;
5121da177e4SLinus Torvalds 		case 2:
5134085399dSKenji Kaneshige 			slot_cmd = SET_ATTN_BLINK;	/* BLINK */
5141da177e4SLinus Torvalds 			break;
5151da177e4SLinus Torvalds 		default:
5161da177e4SLinus Torvalds 			return -1;
5171da177e4SLinus Torvalds 	}
5181da177e4SLinus Torvalds 
519d4fbf600SKenji Kaneshige 	return shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
5201da177e4SLinus Torvalds }
5211da177e4SLinus Torvalds 
5221da177e4SLinus Torvalds 
hpc_set_green_led_on(struct slot * slot)5231da177e4SLinus Torvalds static void hpc_set_green_led_on(struct slot *slot)
5241da177e4SLinus Torvalds {
5254085399dSKenji Kaneshige 	shpc_write_cmd(slot, slot->hp_slot, SET_PWR_ON);
5261da177e4SLinus Torvalds }
5271da177e4SLinus Torvalds 
hpc_set_green_led_off(struct slot * slot)5281da177e4SLinus Torvalds static void hpc_set_green_led_off(struct slot *slot)
5291da177e4SLinus Torvalds {
5304085399dSKenji Kaneshige 	shpc_write_cmd(slot, slot->hp_slot, SET_PWR_OFF);
5311da177e4SLinus Torvalds }
5321da177e4SLinus Torvalds 
hpc_set_green_led_blink(struct slot * slot)5331da177e4SLinus Torvalds static void hpc_set_green_led_blink(struct slot *slot)
5341da177e4SLinus Torvalds {
5354085399dSKenji Kaneshige 	shpc_write_cmd(slot, slot->hp_slot, SET_PWR_BLINK);
5361da177e4SLinus Torvalds }
5371da177e4SLinus Torvalds 
hpc_release_ctlr(struct controller * ctrl)5381da177e4SLinus Torvalds static void hpc_release_ctlr(struct controller *ctrl)
5391da177e4SLinus Torvalds {
540f7391f53SKenji Kaneshige 	int i;
541d49f2c49SKenji Kaneshige 	u32 slot_reg, serr_int;
5421da177e4SLinus Torvalds 
543f7391f53SKenji Kaneshige 	/*
544795eb5c4SKenji Kaneshige 	 * Mask event interrupts and SERRs of all slots
545f7391f53SKenji Kaneshige 	 */
546795eb5c4SKenji Kaneshige 	for (i = 0; i < ctrl->num_slots; i++) {
547795eb5c4SKenji Kaneshige 		slot_reg = shpc_readl(ctrl, SLOT_REG(i));
548795eb5c4SKenji Kaneshige 		slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
549795eb5c4SKenji Kaneshige 			     BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
550795eb5c4SKenji Kaneshige 			     CON_PFAULT_INTR_MASK   | MRL_CHANGE_SERR_MASK |
551795eb5c4SKenji Kaneshige 			     CON_PFAULT_SERR_MASK);
552795eb5c4SKenji Kaneshige 		slot_reg &= ~SLOT_REG_RSVDZ_MASK;
553795eb5c4SKenji Kaneshige 		shpc_writel(ctrl, SLOT_REG(i), slot_reg);
554795eb5c4SKenji Kaneshige 	}
555f7391f53SKenji Kaneshige 
556f7391f53SKenji Kaneshige 	cleanup_slots(ctrl);
557f7391f53SKenji Kaneshige 
558d49f2c49SKenji Kaneshige 	/*
5593609801eSJoe Perches 	 * Mask SERR and System Interrupt generation
560d49f2c49SKenji Kaneshige 	 */
561d49f2c49SKenji Kaneshige 	serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
562d49f2c49SKenji Kaneshige 	serr_int |= (GLOBAL_INTR_MASK  | GLOBAL_SERR_MASK |
563d49f2c49SKenji Kaneshige 		     COMMAND_INTR_MASK | ARBITER_SERR_MASK);
564d49f2c49SKenji Kaneshige 	serr_int &= ~SERR_INTR_RSVDZ_MASK;
565d49f2c49SKenji Kaneshige 	shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
566d49f2c49SKenji Kaneshige 
5670abe68ceSKenji Kaneshige 	if (shpchp_poll_mode)
5680abe68ceSKenji Kaneshige 		del_timer(&ctrl->poll_timer);
5690abe68ceSKenji Kaneshige 	else {
5700abe68ceSKenji Kaneshige 		free_irq(ctrl->pci_dev->irq, ctrl);
5710abe68ceSKenji Kaneshige 		pci_disable_msi(ctrl->pci_dev);
5721da177e4SLinus Torvalds 	}
573f7391f53SKenji Kaneshige 
5740abe68ceSKenji Kaneshige 	iounmap(ctrl->creg);
5750455986cSKenji Kaneshige 	release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
5761da177e4SLinus Torvalds }
5771da177e4SLinus Torvalds 
hpc_power_on_slot(struct slot * slot)5781da177e4SLinus Torvalds static int hpc_power_on_slot(struct slot *slot)
5791da177e4SLinus Torvalds {
580d4fbf600SKenji Kaneshige 	int retval;
5811da177e4SLinus Torvalds 
5824085399dSKenji Kaneshige 	retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_PWR);
5831555b33dSKenji Kaneshige 	if (retval)
584f98ca311STaku Izumi 		ctrl_err(slot->ctrl, "%s: Write command failed!\n", __func__);
5851555b33dSKenji Kaneshige 
586d4fbf600SKenji Kaneshige 	return retval;
5871da177e4SLinus Torvalds }
5881da177e4SLinus Torvalds 
hpc_slot_enable(struct slot * slot)5891da177e4SLinus Torvalds static int hpc_slot_enable(struct slot *slot)
5901da177e4SLinus Torvalds {
591d4fbf600SKenji Kaneshige 	int retval;
5921da177e4SLinus Torvalds 
5934085399dSKenji Kaneshige 	/* Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */
5944085399dSKenji Kaneshige 	retval = shpc_write_cmd(slot, slot->hp_slot,
5954085399dSKenji Kaneshige 			SET_SLOT_ENABLE | SET_PWR_BLINK | SET_ATTN_OFF);
5961555b33dSKenji Kaneshige 	if (retval)
597f98ca311STaku Izumi 		ctrl_err(slot->ctrl, "%s: Write command failed!\n", __func__);
5981da177e4SLinus Torvalds 
5991555b33dSKenji Kaneshige 	return retval;
6001da177e4SLinus Torvalds }
6011da177e4SLinus Torvalds 
hpc_slot_disable(struct slot * slot)6021da177e4SLinus Torvalds static int hpc_slot_disable(struct slot *slot)
6031da177e4SLinus Torvalds {
604d4fbf600SKenji Kaneshige 	int retval;
6051da177e4SLinus Torvalds 
6064085399dSKenji Kaneshige 	/* Slot - Disable, Power Indicator - Off, Attention Indicator - On */
6074085399dSKenji Kaneshige 	retval = shpc_write_cmd(slot, slot->hp_slot,
6084085399dSKenji Kaneshige 			SET_SLOT_DISABLE | SET_PWR_OFF | SET_ATTN_ON);
6091555b33dSKenji Kaneshige 	if (retval)
610f98ca311STaku Izumi 		ctrl_err(slot->ctrl, "%s: Write command failed!\n", __func__);
6111da177e4SLinus Torvalds 
6121555b33dSKenji Kaneshige 	return retval;
6131da177e4SLinus Torvalds }
6141da177e4SLinus Torvalds 
shpc_get_cur_bus_speed(struct controller * ctrl)6153749c51aSMatthew Wilcox static int shpc_get_cur_bus_speed(struct controller *ctrl)
6163749c51aSMatthew Wilcox {
6173749c51aSMatthew Wilcox 	int retval = 0;
6183749c51aSMatthew Wilcox 	struct pci_bus *bus = ctrl->pci_dev->subordinate;
6193749c51aSMatthew Wilcox 	enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
6203749c51aSMatthew Wilcox 	u16 sec_bus_reg = shpc_readw(ctrl, SEC_BUS_CONFIG);
6213749c51aSMatthew Wilcox 	u8 pi = shpc_readb(ctrl, PROG_INTERFACE);
6223749c51aSMatthew Wilcox 	u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7);
6233749c51aSMatthew Wilcox 
6243749c51aSMatthew Wilcox 	if ((pi == 1) && (speed_mode > 4)) {
6253749c51aSMatthew Wilcox 		retval = -ENODEV;
6263749c51aSMatthew Wilcox 		goto out;
6273749c51aSMatthew Wilcox 	}
6283749c51aSMatthew Wilcox 
6293749c51aSMatthew Wilcox 	switch (speed_mode) {
6303749c51aSMatthew Wilcox 	case 0x0:
6313749c51aSMatthew Wilcox 		bus_speed = PCI_SPEED_33MHz;
6323749c51aSMatthew Wilcox 		break;
6333749c51aSMatthew Wilcox 	case 0x1:
6343749c51aSMatthew Wilcox 		bus_speed = PCI_SPEED_66MHz;
6353749c51aSMatthew Wilcox 		break;
6363749c51aSMatthew Wilcox 	case 0x2:
6373749c51aSMatthew Wilcox 		bus_speed = PCI_SPEED_66MHz_PCIX;
6383749c51aSMatthew Wilcox 		break;
6393749c51aSMatthew Wilcox 	case 0x3:
6403749c51aSMatthew Wilcox 		bus_speed = PCI_SPEED_100MHz_PCIX;
6413749c51aSMatthew Wilcox 		break;
6423749c51aSMatthew Wilcox 	case 0x4:
6433749c51aSMatthew Wilcox 		bus_speed = PCI_SPEED_133MHz_PCIX;
6443749c51aSMatthew Wilcox 		break;
6453749c51aSMatthew Wilcox 	case 0x5:
6463749c51aSMatthew Wilcox 		bus_speed = PCI_SPEED_66MHz_PCIX_ECC;
6473749c51aSMatthew Wilcox 		break;
6483749c51aSMatthew Wilcox 	case 0x6:
6493749c51aSMatthew Wilcox 		bus_speed = PCI_SPEED_100MHz_PCIX_ECC;
6503749c51aSMatthew Wilcox 		break;
6513749c51aSMatthew Wilcox 	case 0x7:
6523749c51aSMatthew Wilcox 		bus_speed = PCI_SPEED_133MHz_PCIX_ECC;
6533749c51aSMatthew Wilcox 		break;
6543749c51aSMatthew Wilcox 	case 0x8:
6553749c51aSMatthew Wilcox 		bus_speed = PCI_SPEED_66MHz_PCIX_266;
6563749c51aSMatthew Wilcox 		break;
6573749c51aSMatthew Wilcox 	case 0x9:
6583749c51aSMatthew Wilcox 		bus_speed = PCI_SPEED_100MHz_PCIX_266;
6593749c51aSMatthew Wilcox 		break;
6603749c51aSMatthew Wilcox 	case 0xa:
6613749c51aSMatthew Wilcox 		bus_speed = PCI_SPEED_133MHz_PCIX_266;
6623749c51aSMatthew Wilcox 		break;
6633749c51aSMatthew Wilcox 	case 0xb:
6643749c51aSMatthew Wilcox 		bus_speed = PCI_SPEED_66MHz_PCIX_533;
6653749c51aSMatthew Wilcox 		break;
6663749c51aSMatthew Wilcox 	case 0xc:
6673749c51aSMatthew Wilcox 		bus_speed = PCI_SPEED_100MHz_PCIX_533;
6683749c51aSMatthew Wilcox 		break;
6693749c51aSMatthew Wilcox 	case 0xd:
6703749c51aSMatthew Wilcox 		bus_speed = PCI_SPEED_133MHz_PCIX_533;
6713749c51aSMatthew Wilcox 		break;
6723749c51aSMatthew Wilcox 	default:
6733749c51aSMatthew Wilcox 		retval = -ENODEV;
6743749c51aSMatthew Wilcox 		break;
6753749c51aSMatthew Wilcox 	}
6763749c51aSMatthew Wilcox 
6773749c51aSMatthew Wilcox  out:
6783749c51aSMatthew Wilcox 	bus->cur_bus_speed = bus_speed;
6793749c51aSMatthew Wilcox 	dbg("Current bus speed = %d\n", bus_speed);
6803749c51aSMatthew Wilcox 	return retval;
6813749c51aSMatthew Wilcox }
6823749c51aSMatthew Wilcox 
6833749c51aSMatthew Wilcox 
hpc_set_bus_speed_mode(struct slot * slot,enum pci_bus_speed value)6841da177e4SLinus Torvalds static int hpc_set_bus_speed_mode(struct slot *slot, enum pci_bus_speed value)
6851da177e4SLinus Torvalds {
6860afabe90SKenji Kaneshige 	int retval;
68775d97c59SKenji Kaneshige 	struct controller *ctrl = slot->ctrl;
6880afabe90SKenji Kaneshige 	u8 pi, cmd;
6891da177e4SLinus Torvalds 
69075d97c59SKenji Kaneshige 	pi = shpc_readb(ctrl, PROG_INTERFACE);
6910afabe90SKenji Kaneshige 	if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX))
6920afabe90SKenji Kaneshige 		return -EINVAL;
6931da177e4SLinus Torvalds 
6941da177e4SLinus Torvalds 	switch (value) {
6950afabe90SKenji Kaneshige 	case PCI_SPEED_33MHz:
6960afabe90SKenji Kaneshige 		cmd = SETA_PCI_33MHZ;
6971da177e4SLinus Torvalds 		break;
6980afabe90SKenji Kaneshige 	case PCI_SPEED_66MHz:
6990afabe90SKenji Kaneshige 		cmd = SETA_PCI_66MHZ;
7001da177e4SLinus Torvalds 		break;
7010afabe90SKenji Kaneshige 	case PCI_SPEED_66MHz_PCIX:
7020afabe90SKenji Kaneshige 		cmd = SETA_PCIX_66MHZ;
7031da177e4SLinus Torvalds 		break;
7040afabe90SKenji Kaneshige 	case PCI_SPEED_100MHz_PCIX:
7050afabe90SKenji Kaneshige 		cmd = SETA_PCIX_100MHZ;
7061da177e4SLinus Torvalds 		break;
7070afabe90SKenji Kaneshige 	case PCI_SPEED_133MHz_PCIX:
7080afabe90SKenji Kaneshige 		cmd = SETA_PCIX_133MHZ;
7090afabe90SKenji Kaneshige 		break;
7100afabe90SKenji Kaneshige 	case PCI_SPEED_66MHz_PCIX_ECC:
7110afabe90SKenji Kaneshige 		cmd = SETB_PCIX_66MHZ_EM;
7120afabe90SKenji Kaneshige 		break;
7130afabe90SKenji Kaneshige 	case PCI_SPEED_100MHz_PCIX_ECC:
7140afabe90SKenji Kaneshige 		cmd = SETB_PCIX_100MHZ_EM;
7150afabe90SKenji Kaneshige 		break;
7160afabe90SKenji Kaneshige 	case PCI_SPEED_133MHz_PCIX_ECC:
7170afabe90SKenji Kaneshige 		cmd = SETB_PCIX_133MHZ_EM;
7180afabe90SKenji Kaneshige 		break;
7190afabe90SKenji Kaneshige 	case PCI_SPEED_66MHz_PCIX_266:
7200afabe90SKenji Kaneshige 		cmd = SETB_PCIX_66MHZ_266;
7210afabe90SKenji Kaneshige 		break;
7220afabe90SKenji Kaneshige 	case PCI_SPEED_100MHz_PCIX_266:
7230afabe90SKenji Kaneshige 		cmd = SETB_PCIX_100MHZ_266;
7240afabe90SKenji Kaneshige 		break;
7250afabe90SKenji Kaneshige 	case PCI_SPEED_133MHz_PCIX_266:
7260afabe90SKenji Kaneshige 		cmd = SETB_PCIX_133MHZ_266;
7270afabe90SKenji Kaneshige 		break;
7280afabe90SKenji Kaneshige 	case PCI_SPEED_66MHz_PCIX_533:
7290afabe90SKenji Kaneshige 		cmd = SETB_PCIX_66MHZ_533;
7300afabe90SKenji Kaneshige 		break;
7310afabe90SKenji Kaneshige 	case PCI_SPEED_100MHz_PCIX_533:
7320afabe90SKenji Kaneshige 		cmd = SETB_PCIX_100MHZ_533;
7330afabe90SKenji Kaneshige 		break;
7340afabe90SKenji Kaneshige 	case PCI_SPEED_133MHz_PCIX_533:
7350afabe90SKenji Kaneshige 		cmd = SETB_PCIX_133MHZ_533;
7361da177e4SLinus Torvalds 		break;
7371da177e4SLinus Torvalds 	default:
7380afabe90SKenji Kaneshige 		return -EINVAL;
7391da177e4SLinus Torvalds 	}
7401da177e4SLinus Torvalds 
7410afabe90SKenji Kaneshige 	retval = shpc_write_cmd(slot, 0, cmd);
7420afabe90SKenji Kaneshige 	if (retval)
743f98ca311STaku Izumi 		ctrl_err(ctrl, "%s: Write command failed!\n", __func__);
7443749c51aSMatthew Wilcox 	else
7453749c51aSMatthew Wilcox 		shpc_get_cur_bus_speed(ctrl);
7461da177e4SLinus Torvalds 
7471da177e4SLinus Torvalds 	return retval;
7481da177e4SLinus Torvalds }
7491da177e4SLinus Torvalds 
shpc_isr(int irq,void * dev_id)7507d12e780SDavid Howells static irqreturn_t shpc_isr(int irq, void *dev_id)
7511da177e4SLinus Torvalds {
752c4cecc19SKenji Kaneshige 	struct controller *ctrl = (struct controller *)dev_id;
753c4cecc19SKenji Kaneshige 	u32 serr_int, slot_reg, intr_loc, intr_loc2;
7541da177e4SLinus Torvalds 	int hp_slot;
7551da177e4SLinus Torvalds 
7561da177e4SLinus Torvalds 	/* Check to see if it was our interrupt */
75775d97c59SKenji Kaneshige 	intr_loc = shpc_readl(ctrl, INTR_LOC);
7581da177e4SLinus Torvalds 	if (!intr_loc)
7591da177e4SLinus Torvalds 		return IRQ_NONE;
760c4cecc19SKenji Kaneshige 
761f98ca311STaku Izumi 	ctrl_dbg(ctrl, "%s: intr_loc = %x\n", __func__, intr_loc);
7621da177e4SLinus Torvalds 
7631da177e4SLinus Torvalds 	if (!shpchp_poll_mode) {
764c4cecc19SKenji Kaneshige 		/*
765c4cecc19SKenji Kaneshige 		 * Mask Global Interrupt Mask - see implementation
766c4cecc19SKenji Kaneshige 		 * note on p. 139 of SHPC spec rev 1.0
767c4cecc19SKenji Kaneshige 		 */
768c4cecc19SKenji Kaneshige 		serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
769c4cecc19SKenji Kaneshige 		serr_int |= GLOBAL_INTR_MASK;
770c4cecc19SKenji Kaneshige 		serr_int &= ~SERR_INTR_RSVDZ_MASK;
771c4cecc19SKenji Kaneshige 		shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
7721da177e4SLinus Torvalds 
77375d97c59SKenji Kaneshige 		intr_loc2 = shpc_readl(ctrl, INTR_LOC);
774f98ca311STaku Izumi 		ctrl_dbg(ctrl, "%s: intr_loc2 = %x\n", __func__, intr_loc2);
7751da177e4SLinus Torvalds 	}
7761da177e4SLinus Torvalds 
777c4cecc19SKenji Kaneshige 	if (intr_loc & CMD_INTR_PENDING) {
7781da177e4SLinus Torvalds 		/*
7791da177e4SLinus Torvalds 		 * Command Complete Interrupt Pending
780f467f618SKenji Kaneshige 		 * RO only - clear by writing 1 to the Command Completion
7811da177e4SLinus Torvalds 		 * Detect bit in Controller SERR-INT register
7821da177e4SLinus Torvalds 		 */
783c4cecc19SKenji Kaneshige 		serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
784c4cecc19SKenji Kaneshige 		serr_int &= ~SERR_INTR_RSVDZ_MASK;
785c4cecc19SKenji Kaneshige 		shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
786c4cecc19SKenji Kaneshige 
7871da177e4SLinus Torvalds 		wake_up_interruptible(&ctrl->queue);
7881da177e4SLinus Torvalds 	}
7891da177e4SLinus Torvalds 
790c4cecc19SKenji Kaneshige 	if (!(intr_loc & ~CMD_INTR_PENDING))
791e4e73041SKenji Kaneshige 		goto out;
7921da177e4SLinus Torvalds 
7931da177e4SLinus Torvalds 	for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
7941da177e4SLinus Torvalds 		/* To find out which slot has interrupt pending */
795c4cecc19SKenji Kaneshige 		if (!(intr_loc & SLOT_INTR_PENDING(hp_slot)))
796c4cecc19SKenji Kaneshige 			continue;
797c4cecc19SKenji Kaneshige 
798c4cecc19SKenji Kaneshige 		slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
799be7bce25STaku Izumi 		ctrl_dbg(ctrl, "Slot %x with intr, slot register = %x\n",
800be7bce25STaku Izumi 			 hp_slot, slot_reg);
801c4cecc19SKenji Kaneshige 
802c4cecc19SKenji Kaneshige 		if (slot_reg & MRL_CHANGE_DETECTED)
8030abe68ceSKenji Kaneshige 			shpchp_handle_switch_change(hp_slot, ctrl);
804c4cecc19SKenji Kaneshige 
805c4cecc19SKenji Kaneshige 		if (slot_reg & BUTTON_PRESS_DETECTED)
8060abe68ceSKenji Kaneshige 			shpchp_handle_attention_button(hp_slot, ctrl);
807c4cecc19SKenji Kaneshige 
808c4cecc19SKenji Kaneshige 		if (slot_reg & PRSNT_CHANGE_DETECTED)
8090abe68ceSKenji Kaneshige 			shpchp_handle_presence_change(hp_slot, ctrl);
810c4cecc19SKenji Kaneshige 
811c4cecc19SKenji Kaneshige 		if (slot_reg & (ISO_PFAULT_DETECTED | CON_PFAULT_DETECTED))
8120abe68ceSKenji Kaneshige 			shpchp_handle_power_fault(hp_slot, ctrl);
8131da177e4SLinus Torvalds 
8141da177e4SLinus Torvalds 		/* Clear all slot events */
815c4cecc19SKenji Kaneshige 		slot_reg &= ~SLOT_REG_RSVDZ_MASK;
816c4cecc19SKenji Kaneshige 		shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg);
8171da177e4SLinus Torvalds 	}
818e4e73041SKenji Kaneshige  out:
8191da177e4SLinus Torvalds 	if (!shpchp_poll_mode) {
8201da177e4SLinus Torvalds 		/* Unmask Global Interrupt Mask */
821c4cecc19SKenji Kaneshige 		serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
822c4cecc19SKenji Kaneshige 		serr_int &= ~(GLOBAL_INTR_MASK | SERR_INTR_RSVDZ_MASK);
823c4cecc19SKenji Kaneshige 		shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
8241da177e4SLinus Torvalds 	}
8251da177e4SLinus Torvalds 
8261da177e4SLinus Torvalds 	return IRQ_HANDLED;
8271da177e4SLinus Torvalds }
8281da177e4SLinus Torvalds 
shpc_get_max_bus_speed(struct controller * ctrl)8293749c51aSMatthew Wilcox static int shpc_get_max_bus_speed(struct controller *ctrl)
8301da177e4SLinus Torvalds {
8310afabe90SKenji Kaneshige 	int retval = 0;
8323749c51aSMatthew Wilcox 	struct pci_bus *bus = ctrl->pci_dev->subordinate;
8331da177e4SLinus Torvalds 	enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
83475d97c59SKenji Kaneshige 	u8 pi = shpc_readb(ctrl, PROG_INTERFACE);
83575d97c59SKenji Kaneshige 	u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1);
83675d97c59SKenji Kaneshige 	u32 slot_avail2 = shpc_readl(ctrl, SLOT_AVAIL2);
8371da177e4SLinus Torvalds 
8381da177e4SLinus Torvalds 	if (pi == 2) {
8396558b6abSKenji Kaneshige 		if (slot_avail2 & SLOT_133MHZ_PCIX_533)
8400afabe90SKenji Kaneshige 			bus_speed = PCI_SPEED_133MHz_PCIX_533;
8416558b6abSKenji Kaneshige 		else if (slot_avail2 & SLOT_100MHZ_PCIX_533)
8420afabe90SKenji Kaneshige 			bus_speed = PCI_SPEED_100MHz_PCIX_533;
8436558b6abSKenji Kaneshige 		else if (slot_avail2 & SLOT_66MHZ_PCIX_533)
8440afabe90SKenji Kaneshige 			bus_speed = PCI_SPEED_66MHz_PCIX_533;
8456558b6abSKenji Kaneshige 		else if (slot_avail2 & SLOT_133MHZ_PCIX_266)
8460afabe90SKenji Kaneshige 			bus_speed = PCI_SPEED_133MHz_PCIX_266;
8476558b6abSKenji Kaneshige 		else if (slot_avail2 & SLOT_100MHZ_PCIX_266)
8480afabe90SKenji Kaneshige 			bus_speed = PCI_SPEED_100MHz_PCIX_266;
8496558b6abSKenji Kaneshige 		else if (slot_avail2 & SLOT_66MHZ_PCIX_266)
8500afabe90SKenji Kaneshige 			bus_speed = PCI_SPEED_66MHz_PCIX_266;
8510afabe90SKenji Kaneshige 	}
8520afabe90SKenji Kaneshige 
8530afabe90SKenji Kaneshige 	if (bus_speed == PCI_SPEED_UNKNOWN) {
8546558b6abSKenji Kaneshige 		if (slot_avail1 & SLOT_133MHZ_PCIX)
8550afabe90SKenji Kaneshige 			bus_speed = PCI_SPEED_133MHz_PCIX;
8566558b6abSKenji Kaneshige 		else if (slot_avail1 & SLOT_100MHZ_PCIX)
8570afabe90SKenji Kaneshige 			bus_speed = PCI_SPEED_100MHz_PCIX;
8586558b6abSKenji Kaneshige 		else if (slot_avail1 & SLOT_66MHZ_PCIX)
8590afabe90SKenji Kaneshige 			bus_speed = PCI_SPEED_66MHz_PCIX;
8606558b6abSKenji Kaneshige 		else if (slot_avail2 & SLOT_66MHZ)
8610afabe90SKenji Kaneshige 			bus_speed = PCI_SPEED_66MHz;
8626558b6abSKenji Kaneshige 		else if (slot_avail1 & SLOT_33MHZ)
8630afabe90SKenji Kaneshige 			bus_speed = PCI_SPEED_33MHz;
8640afabe90SKenji Kaneshige 		else
8650afabe90SKenji Kaneshige 			retval = -ENODEV;
8661da177e4SLinus Torvalds 	}
8671da177e4SLinus Torvalds 
8683749c51aSMatthew Wilcox 	bus->max_bus_speed = bus_speed;
869f98ca311STaku Izumi 	ctrl_dbg(ctrl, "Max bus speed = %d\n", bus_speed);
8701555b33dSKenji Kaneshige 
8711da177e4SLinus Torvalds 	return retval;
8721da177e4SLinus Torvalds }
8731da177e4SLinus Torvalds 
874bd790082SJulia Lawall static const struct hpc_ops shpchp_hpc_ops = {
8751da177e4SLinus Torvalds 	.power_on_slot			= hpc_power_on_slot,
8761da177e4SLinus Torvalds 	.slot_enable			= hpc_slot_enable,
8771da177e4SLinus Torvalds 	.slot_disable			= hpc_slot_disable,
8781da177e4SLinus Torvalds 	.set_bus_speed_mode		= hpc_set_bus_speed_mode,
8791da177e4SLinus Torvalds 	.set_attention_status	= hpc_set_attention_status,
8801da177e4SLinus Torvalds 	.get_power_status		= hpc_get_power_status,
8811da177e4SLinus Torvalds 	.get_attention_status	= hpc_get_attention_status,
8821da177e4SLinus Torvalds 	.get_latch_status		= hpc_get_latch_status,
8831da177e4SLinus Torvalds 	.get_adapter_status		= hpc_get_adapter_status,
8841da177e4SLinus Torvalds 
8851da177e4SLinus Torvalds 	.get_adapter_speed		= hpc_get_adapter_speed,
8861da177e4SLinus Torvalds 	.get_prog_int			= hpc_get_prog_int,
8871da177e4SLinus Torvalds 
8881da177e4SLinus Torvalds 	.query_power_fault		= hpc_query_power_fault,
8891da177e4SLinus Torvalds 	.green_led_on			= hpc_set_green_led_on,
8901da177e4SLinus Torvalds 	.green_led_off			= hpc_set_green_led_off,
8911da177e4SLinus Torvalds 	.green_led_blink		= hpc_set_green_led_blink,
8921da177e4SLinus Torvalds 
8931da177e4SLinus Torvalds 	.release_ctlr			= hpc_release_ctlr,
8941da177e4SLinus Torvalds };
8951da177e4SLinus Torvalds 
shpc_init(struct controller * ctrl,struct pci_dev * pdev)896ee138334Srajesh.shah@intel.com int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
8971da177e4SLinus Torvalds {
898662a98fbSAmol Lad 	int rc = -1, num_slots = 0;
8991da177e4SLinus Torvalds 	u8 hp_slot;
9000455986cSKenji Kaneshige 	u32 shpc_base_offset;
90175d97c59SKenji Kaneshige 	u32 tempdword, slot_reg, slot_config;
9021da177e4SLinus Torvalds 	u8 i;
9031da177e4SLinus Torvalds 
9040455986cSKenji Kaneshige 	ctrl->pci_dev = pdev;  /* pci_dev of the P2P bridge */
905be7bce25STaku Izumi 	ctrl_dbg(ctrl, "Hotplug Controller:\n");
9060455986cSKenji Kaneshige 
9074cac2eb1SBjorn Helgaas 	if (pdev->vendor == PCI_VENDOR_ID_AMD &&
9084cac2eb1SBjorn Helgaas 	    pdev->device == PCI_DEVICE_ID_AMD_GOLAM_7450) {
9090455986cSKenji Kaneshige 		/* amd shpc driver doesn't use Base Offset; assume 0 */
9100455986cSKenji Kaneshige 		ctrl->mmio_base = pci_resource_start(pdev, 0);
9110455986cSKenji Kaneshige 		ctrl->mmio_size = pci_resource_len(pdev, 0);
9121da177e4SLinus Torvalds 	} else {
9130455986cSKenji Kaneshige 		ctrl->cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC);
9140455986cSKenji Kaneshige 		if (!ctrl->cap_offset) {
915be7bce25STaku Izumi 			ctrl_err(ctrl, "Cannot find PCI capability\n");
9160abe68ceSKenji Kaneshige 			goto abort;
9171da177e4SLinus Torvalds 		}
918be7bce25STaku Izumi 		ctrl_dbg(ctrl, " cap_offset = %x\n", ctrl->cap_offset);
9191da177e4SLinus Torvalds 
92075d97c59SKenji Kaneshige 		rc = shpc_indirect_read(ctrl, 0, &shpc_base_offset);
9211da177e4SLinus Torvalds 		if (rc) {
922be7bce25STaku Izumi 			ctrl_err(ctrl, "Cannot read base_offset\n");
9230abe68ceSKenji Kaneshige 			goto abort;
9241da177e4SLinus Torvalds 		}
9251da177e4SLinus Torvalds 
92675d97c59SKenji Kaneshige 		rc = shpc_indirect_read(ctrl, 3, &tempdword);
9271da177e4SLinus Torvalds 		if (rc) {
928be7bce25STaku Izumi 			ctrl_err(ctrl, "Cannot read slot config\n");
9290abe68ceSKenji Kaneshige 			goto abort;
9301da177e4SLinus Torvalds 		}
9310455986cSKenji Kaneshige 		num_slots = tempdword & SLOT_NUM;
932be7bce25STaku Izumi 		ctrl_dbg(ctrl, " num_slots (indirect) %x\n", num_slots);
9331da177e4SLinus Torvalds 
9340455986cSKenji Kaneshige 		for (i = 0; i < 9 + num_slots; i++) {
93575d97c59SKenji Kaneshige 			rc = shpc_indirect_read(ctrl, i, &tempdword);
9361da177e4SLinus Torvalds 			if (rc) {
937227f0647SRyan Desfosses 				ctrl_err(ctrl, "Cannot read creg (index = %d)\n",
938227f0647SRyan Desfosses 					 i);
9390abe68ceSKenji Kaneshige 				goto abort;
9401da177e4SLinus Torvalds 			}
941be7bce25STaku Izumi 			ctrl_dbg(ctrl, " offset %d: value %x\n", i, tempdword);
9421da177e4SLinus Torvalds 		}
9430455986cSKenji Kaneshige 
9440455986cSKenji Kaneshige 		ctrl->mmio_base =
9450455986cSKenji Kaneshige 			pci_resource_start(pdev, 0) + shpc_base_offset;
9460455986cSKenji Kaneshige 		ctrl->mmio_size = 0x24 + 0x4 * num_slots;
9471da177e4SLinus Torvalds 	}
9481da177e4SLinus Torvalds 
949f98ca311STaku Izumi 	ctrl_info(ctrl, "HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
950f98ca311STaku Izumi 		  pdev->vendor, pdev->device, pdev->subsystem_vendor,
9511da177e4SLinus Torvalds 		  pdev->subsystem_device);
9521da177e4SLinus Torvalds 
953662a98fbSAmol Lad 	rc = pci_enable_device(pdev);
954662a98fbSAmol Lad 	if (rc) {
955be7bce25STaku Izumi 		ctrl_err(ctrl, "pci_enable_device failed\n");
9560abe68ceSKenji Kaneshige 		goto abort;
957662a98fbSAmol Lad 	}
9581da177e4SLinus Torvalds 
9590455986cSKenji Kaneshige 	if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) {
960be7bce25STaku Izumi 		ctrl_err(ctrl, "Cannot reserve MMIO region\n");
961662a98fbSAmol Lad 		rc = -1;
9620abe68ceSKenji Kaneshige 		goto abort;
9631da177e4SLinus Torvalds 	}
9641da177e4SLinus Torvalds 
9650abe68ceSKenji Kaneshige 	ctrl->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size);
9660abe68ceSKenji Kaneshige 	if (!ctrl->creg) {
967be7bce25STaku Izumi 		ctrl_err(ctrl, "Cannot remap MMIO region %lx @ %lx\n",
968be7bce25STaku Izumi 			 ctrl->mmio_size, ctrl->mmio_base);
9690455986cSKenji Kaneshige 		release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
970662a98fbSAmol Lad 		rc = -1;
9710abe68ceSKenji Kaneshige 		goto abort;
9721da177e4SLinus Torvalds 	}
973be7bce25STaku Izumi 	ctrl_dbg(ctrl, "ctrl->creg %p\n", ctrl->creg);
9741da177e4SLinus Torvalds 
9756aa4cdd0SIngo Molnar 	mutex_init(&ctrl->crit_sect);
976d29aaddaSKenji Kaneshige 	mutex_init(&ctrl->cmd_lock);
977d29aaddaSKenji Kaneshige 
9781da177e4SLinus Torvalds 	/* Setup wait queue */
9791da177e4SLinus Torvalds 	init_waitqueue_head(&ctrl->queue);
9801da177e4SLinus Torvalds 
98175d97c59SKenji Kaneshige 	ctrl->hpc_ops = &shpchp_hpc_ops;
98275d97c59SKenji Kaneshige 
9831da177e4SLinus Torvalds 	/* Return PCI Controller Info */
98475d97c59SKenji Kaneshige 	slot_config = shpc_readl(ctrl, SLOT_CONFIG);
9850abe68ceSKenji Kaneshige 	ctrl->slot_device_offset = (slot_config & FIRST_DEV_NUM) >> 8;
9860abe68ceSKenji Kaneshige 	ctrl->num_slots = slot_config & SLOT_NUM;
9870abe68ceSKenji Kaneshige 	ctrl->first_slot = (slot_config & PSN) >> 16;
9880abe68ceSKenji Kaneshige 	ctrl->slot_num_inc = ((slot_config & UPDOWN) >> 29) ? 1 : -1;
9891da177e4SLinus Torvalds 
9901da177e4SLinus Torvalds 	/* Mask Global Interrupt Mask & Command Complete Interrupt Mask */
99175d97c59SKenji Kaneshige 	tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
992be7bce25STaku Izumi 	ctrl_dbg(ctrl, "SERR_INTR_ENABLE = %x\n", tempdword);
993e7138723SKenji Kaneshige 	tempdword |= (GLOBAL_INTR_MASK  | GLOBAL_SERR_MASK |
994e7138723SKenji Kaneshige 		      COMMAND_INTR_MASK | ARBITER_SERR_MASK);
995e7138723SKenji Kaneshige 	tempdword &= ~SERR_INTR_RSVDZ_MASK;
99675d97c59SKenji Kaneshige 	shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword);
99775d97c59SKenji Kaneshige 	tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
998be7bce25STaku Izumi 	ctrl_dbg(ctrl, "SERR_INTR_ENABLE = %x\n", tempdword);
9991da177e4SLinus Torvalds 
10001da177e4SLinus Torvalds 	/* Mask the MRL sensor SERR Mask of individual slot in
10011da177e4SLinus Torvalds 	 * Slot SERR-INT Mask & clear all the existing event if any
10021da177e4SLinus Torvalds 	 */
10030abe68ceSKenji Kaneshige 	for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
10042b34da7eSKenji Kaneshige 		slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
1005be7bce25STaku Izumi 		ctrl_dbg(ctrl, "Default Logical Slot Register %d value %x\n",
1006be7bce25STaku Izumi 			 hp_slot, slot_reg);
1007795eb5c4SKenji Kaneshige 		slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
1008795eb5c4SKenji Kaneshige 			     BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
1009795eb5c4SKenji Kaneshige 			     CON_PFAULT_INTR_MASK   | MRL_CHANGE_SERR_MASK |
1010795eb5c4SKenji Kaneshige 			     CON_PFAULT_SERR_MASK);
1011795eb5c4SKenji Kaneshige 		slot_reg &= ~SLOT_REG_RSVDZ_MASK;
1012795eb5c4SKenji Kaneshige 		shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg);
10131da177e4SLinus Torvalds 	}
10141da177e4SLinus Torvalds 
10150abe68ceSKenji Kaneshige 	if (shpchp_poll_mode) {
10160abe68ceSKenji Kaneshige 		/* Install interrupt polling timer. Start with 10 sec delay */
10173691314aSKees Cook 		timer_setup(&ctrl->poll_timer, int_poll_timeout, 0);
10180abe68ceSKenji Kaneshige 		start_int_poll_timer(ctrl, 10);
10191da177e4SLinus Torvalds 	} else {
10201da177e4SLinus Torvalds 		/* Installs the interrupt handler */
10211da177e4SLinus Torvalds 		rc = pci_enable_msi(pdev);
10221da177e4SLinus Torvalds 		if (rc) {
1023227f0647SRyan Desfosses 			ctrl_info(ctrl, "Can't get msi for the hotplug controller\n");
1024227f0647SRyan Desfosses 			ctrl_info(ctrl, "Use INTx for the hotplug controller\n");
102548b79a14SAleksandr Bezzubikov 		} else {
102648b79a14SAleksandr Bezzubikov 			pci_set_master(pdev);
10270abe68ceSKenji Kaneshige 		}
10281da177e4SLinus Torvalds 
10290abe68ceSKenji Kaneshige 		rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED,
10300abe68ceSKenji Kaneshige 				 MY_NAME, (void *)ctrl);
1031e24dcbefSTejun Heo 		ctrl_dbg(ctrl, "request_irq %d (returns %d)\n",
1032e24dcbefSTejun Heo 			 ctrl->pci_dev->irq, rc);
10331da177e4SLinus Torvalds 		if (rc) {
1034227f0647SRyan Desfosses 			ctrl_err(ctrl, "Can't get irq %d for the hotplug controller\n",
1035227f0647SRyan Desfosses 				 ctrl->pci_dev->irq);
10360abe68ceSKenji Kaneshige 			goto abort_iounmap;
10371da177e4SLinus Torvalds 		}
10381da177e4SLinus Torvalds 	}
1039be7bce25STaku Izumi 	ctrl_dbg(ctrl, "HPC at %s irq=%x\n", pci_name(pdev), pdev->irq);
10401da177e4SLinus Torvalds 
10413749c51aSMatthew Wilcox 	shpc_get_max_bus_speed(ctrl);
10423749c51aSMatthew Wilcox 	shpc_get_cur_bus_speed(ctrl);
10433749c51aSMatthew Wilcox 
1044795eb5c4SKenji Kaneshige 	/*
1045795eb5c4SKenji Kaneshige 	 * Unmask all event interrupts of all slots
1046795eb5c4SKenji Kaneshige 	 */
10470abe68ceSKenji Kaneshige 	for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
10482b34da7eSKenji Kaneshige 		slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
1049be7bce25STaku Izumi 		ctrl_dbg(ctrl, "Default Logical Slot Register %d value %x\n",
1050be7bce25STaku Izumi 			 hp_slot, slot_reg);
1051795eb5c4SKenji Kaneshige 		slot_reg &= ~(PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
1052795eb5c4SKenji Kaneshige 			      BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
1053795eb5c4SKenji Kaneshige 			      CON_PFAULT_INTR_MASK | SLOT_REG_RSVDZ_MASK);
1054795eb5c4SKenji Kaneshige 		shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg);
10551da177e4SLinus Torvalds 	}
10561da177e4SLinus Torvalds 	if (!shpchp_poll_mode) {
10571da177e4SLinus Torvalds 		/* Unmask all general input interrupts and SERR */
105875d97c59SKenji Kaneshige 		tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
1059e7138723SKenji Kaneshige 		tempdword &= ~(GLOBAL_INTR_MASK | COMMAND_INTR_MASK |
1060e7138723SKenji Kaneshige 			       SERR_INTR_RSVDZ_MASK);
106175d97c59SKenji Kaneshige 		shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword);
106275d97c59SKenji Kaneshige 		tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
1063be7bce25STaku Izumi 		ctrl_dbg(ctrl, "SERR_INTR_ENABLE = %x\n", tempdword);
10641da177e4SLinus Torvalds 	}
10651da177e4SLinus Torvalds 
10661da177e4SLinus Torvalds 	return 0;
10671da177e4SLinus Torvalds 
10681da177e4SLinus Torvalds 	/* We end up here for the many possible ways to fail this API.  */
10690abe68ceSKenji Kaneshige abort_iounmap:
10700abe68ceSKenji Kaneshige 	iounmap(ctrl->creg);
10711da177e4SLinus Torvalds abort:
1072662a98fbSAmol Lad 	return rc;
10731da177e4SLinus Torvalds }
1074