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