11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Standard PCI Hot Plug Driver 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 1995,2001 Compaq Computer Corporation 51da177e4SLinus Torvalds * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) 61da177e4SLinus Torvalds * Copyright (C) 2001 IBM Corp. 71da177e4SLinus Torvalds * Copyright (C) 2003-2004 Intel Corporation 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * All rights reserved. 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 121da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 131da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or (at 141da177e4SLinus Torvalds * your option) any later version. 151da177e4SLinus Torvalds * 161da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, but 171da177e4SLinus Torvalds * WITHOUT ANY WARRANTY; without even the implied warranty of 181da177e4SLinus Torvalds * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 191da177e4SLinus Torvalds * NON INFRINGEMENT. See the GNU General Public License for more 201da177e4SLinus Torvalds * details. 211da177e4SLinus Torvalds * 221da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License 231da177e4SLinus Torvalds * along with this program; if not, write to the Free Software 241da177e4SLinus Torvalds * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 251da177e4SLinus Torvalds * 268cf4c195SKristen Accardi * Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com> 271da177e4SLinus Torvalds * 281da177e4SLinus Torvalds */ 291da177e4SLinus Torvalds 301da177e4SLinus Torvalds #include <linux/kernel.h> 311da177e4SLinus Torvalds #include <linux/module.h> 321da177e4SLinus Torvalds #include <linux/types.h> 331da177e4SLinus Torvalds #include <linux/pci.h> 34d4d28dd4SAndrew Morton #include <linux/interrupt.h> 35d4d28dd4SAndrew Morton 361da177e4SLinus Torvalds #include "shpchp.h" 371da177e4SLinus Torvalds 381da177e4SLinus Torvalds /* Slot Available Register I field definition */ 391da177e4SLinus Torvalds #define SLOT_33MHZ 0x0000001f 401da177e4SLinus Torvalds #define SLOT_66MHZ_PCIX 0x00001f00 411da177e4SLinus Torvalds #define SLOT_100MHZ_PCIX 0x001f0000 421da177e4SLinus Torvalds #define SLOT_133MHZ_PCIX 0x1f000000 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds /* Slot Available Register II field definition */ 451da177e4SLinus Torvalds #define SLOT_66MHZ 0x0000001f 461da177e4SLinus Torvalds #define SLOT_66MHZ_PCIX_266 0x00000f00 471da177e4SLinus Torvalds #define SLOT_100MHZ_PCIX_266 0x0000f000 481da177e4SLinus Torvalds #define SLOT_133MHZ_PCIX_266 0x000f0000 491da177e4SLinus Torvalds #define SLOT_66MHZ_PCIX_533 0x00f00000 501da177e4SLinus Torvalds #define SLOT_100MHZ_PCIX_533 0x0f000000 511da177e4SLinus Torvalds #define SLOT_133MHZ_PCIX_533 0xf0000000 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds /* Slot Configuration */ 541da177e4SLinus Torvalds #define SLOT_NUM 0x0000001F 551da177e4SLinus Torvalds #define FIRST_DEV_NUM 0x00001F00 561da177e4SLinus Torvalds #define PSN 0x07FF0000 571da177e4SLinus Torvalds #define UPDOWN 0x20000000 581da177e4SLinus Torvalds #define MRLSENSOR 0x40000000 591da177e4SLinus Torvalds #define ATTN_BUTTON 0x80000000 601da177e4SLinus Torvalds 612b34da7eSKenji Kaneshige /* 62c4cecc19SKenji Kaneshige * Interrupt Locator Register definitions 63c4cecc19SKenji Kaneshige */ 64c4cecc19SKenji Kaneshige #define CMD_INTR_PENDING (1 << 0) 65c4cecc19SKenji Kaneshige #define SLOT_INTR_PENDING(i) (1 << (i + 1)) 66c4cecc19SKenji Kaneshige 67c4cecc19SKenji Kaneshige /* 68e7138723SKenji Kaneshige * Controller SERR-INT Register 69e7138723SKenji Kaneshige */ 70e7138723SKenji Kaneshige #define GLOBAL_INTR_MASK (1 << 0) 71e7138723SKenji Kaneshige #define GLOBAL_SERR_MASK (1 << 1) 72e7138723SKenji Kaneshige #define COMMAND_INTR_MASK (1 << 2) 73e7138723SKenji Kaneshige #define ARBITER_SERR_MASK (1 << 3) 74e7138723SKenji Kaneshige #define COMMAND_DETECTED (1 << 16) 75e7138723SKenji Kaneshige #define ARBITER_DETECTED (1 << 17) 76e7138723SKenji Kaneshige #define SERR_INTR_RSVDZ_MASK 0xfffc0000 77e7138723SKenji Kaneshige 78e7138723SKenji Kaneshige /* 792b34da7eSKenji Kaneshige * Logical Slot Register definitions 802b34da7eSKenji Kaneshige */ 812b34da7eSKenji Kaneshige #define SLOT_REG(i) (SLOT1 + (4 * i)) 822b34da7eSKenji Kaneshige 835858759cSKenji Kaneshige #define SLOT_STATE_SHIFT (0) 845858759cSKenji Kaneshige #define SLOT_STATE_MASK (3 << 0) 855858759cSKenji Kaneshige #define SLOT_STATE_PWRONLY (1) 865858759cSKenji Kaneshige #define SLOT_STATE_ENABLED (2) 875858759cSKenji Kaneshige #define SLOT_STATE_DISABLED (3) 885858759cSKenji Kaneshige #define PWR_LED_STATE_SHIFT (2) 895858759cSKenji Kaneshige #define PWR_LED_STATE_MASK (3 << 2) 905858759cSKenji Kaneshige #define ATN_LED_STATE_SHIFT (4) 915858759cSKenji Kaneshige #define ATN_LED_STATE_MASK (3 << 4) 925858759cSKenji Kaneshige #define ATN_LED_STATE_ON (1) 935858759cSKenji Kaneshige #define ATN_LED_STATE_BLINK (2) 945858759cSKenji Kaneshige #define ATN_LED_STATE_OFF (3) 955858759cSKenji Kaneshige #define POWER_FAULT (1 << 6) 965858759cSKenji Kaneshige #define ATN_BUTTON (1 << 7) 975858759cSKenji Kaneshige #define MRL_SENSOR (1 << 8) 985858759cSKenji Kaneshige #define MHZ66_CAP (1 << 9) 995858759cSKenji Kaneshige #define PRSNT_SHIFT (10) 1005858759cSKenji Kaneshige #define PRSNT_MASK (3 << 10) 1015858759cSKenji Kaneshige #define PCIX_CAP_SHIFT (12) 1025858759cSKenji Kaneshige #define PCIX_CAP_MASK_PI1 (3 << 12) 1035858759cSKenji Kaneshige #define PCIX_CAP_MASK_PI2 (7 << 12) 1045858759cSKenji Kaneshige #define PRSNT_CHANGE_DETECTED (1 << 16) 1055858759cSKenji Kaneshige #define ISO_PFAULT_DETECTED (1 << 17) 1065858759cSKenji Kaneshige #define BUTTON_PRESS_DETECTED (1 << 18) 1075858759cSKenji Kaneshige #define MRL_CHANGE_DETECTED (1 << 19) 1085858759cSKenji Kaneshige #define CON_PFAULT_DETECTED (1 << 20) 1095858759cSKenji Kaneshige #define PRSNT_CHANGE_INTR_MASK (1 << 24) 1105858759cSKenji Kaneshige #define ISO_PFAULT_INTR_MASK (1 << 25) 1115858759cSKenji Kaneshige #define BUTTON_PRESS_INTR_MASK (1 << 26) 1125858759cSKenji Kaneshige #define MRL_CHANGE_INTR_MASK (1 << 27) 1135858759cSKenji Kaneshige #define CON_PFAULT_INTR_MASK (1 << 28) 1145858759cSKenji Kaneshige #define MRL_CHANGE_SERR_MASK (1 << 29) 1155858759cSKenji Kaneshige #define CON_PFAULT_SERR_MASK (1 << 30) 1165858759cSKenji Kaneshige #define SLOT_REG_RSVDZ_MASK (1 << 15) | (7 << 21) 1171da177e4SLinus Torvalds 1184085399dSKenji Kaneshige /* 1194085399dSKenji Kaneshige * SHPC Command Code definitnions 1204085399dSKenji Kaneshige * 1214085399dSKenji Kaneshige * Slot Operation 00h - 3Fh 1224085399dSKenji Kaneshige * Set Bus Segment Speed/Mode A 40h - 47h 1234085399dSKenji Kaneshige * Power-Only All Slots 48h 1244085399dSKenji Kaneshige * Enable All Slots 49h 1254085399dSKenji Kaneshige * Set Bus Segment Speed/Mode B (PI=2) 50h - 5Fh 1264085399dSKenji Kaneshige * Reserved Command Codes 60h - BFh 1274085399dSKenji Kaneshige * Vendor Specific Commands C0h - FFh 1284085399dSKenji Kaneshige */ 1294085399dSKenji Kaneshige #define SET_SLOT_PWR 0x01 /* Slot Operation */ 1301da177e4SLinus Torvalds #define SET_SLOT_ENABLE 0x02 1311da177e4SLinus Torvalds #define SET_SLOT_DISABLE 0x03 1321da177e4SLinus Torvalds #define SET_PWR_ON 0x04 1331da177e4SLinus Torvalds #define SET_PWR_BLINK 0x08 1344085399dSKenji Kaneshige #define SET_PWR_OFF 0x0c 1354085399dSKenji Kaneshige #define SET_ATTN_ON 0x10 1364085399dSKenji Kaneshige #define SET_ATTN_BLINK 0x20 1374085399dSKenji Kaneshige #define SET_ATTN_OFF 0x30 1384085399dSKenji Kaneshige #define SETA_PCI_33MHZ 0x40 /* Set Bus Segment Speed/Mode A */ 1391da177e4SLinus Torvalds #define SETA_PCI_66MHZ 0x41 1401da177e4SLinus Torvalds #define SETA_PCIX_66MHZ 0x42 1411da177e4SLinus Torvalds #define SETA_PCIX_100MHZ 0x43 1421da177e4SLinus Torvalds #define SETA_PCIX_133MHZ 0x44 1434085399dSKenji Kaneshige #define SETA_RESERVED1 0x45 1444085399dSKenji Kaneshige #define SETA_RESERVED2 0x46 1454085399dSKenji Kaneshige #define SETA_RESERVED3 0x47 1464085399dSKenji Kaneshige #define SET_PWR_ONLY_ALL 0x48 /* Power-Only All Slots */ 1474085399dSKenji Kaneshige #define SET_ENABLE_ALL 0x49 /* Enable All Slots */ 1484085399dSKenji Kaneshige #define SETB_PCI_33MHZ 0x50 /* Set Bus Segment Speed/Mode B */ 1491da177e4SLinus Torvalds #define SETB_PCI_66MHZ 0x51 1501da177e4SLinus Torvalds #define SETB_PCIX_66MHZ_PM 0x52 1511da177e4SLinus Torvalds #define SETB_PCIX_100MHZ_PM 0x53 1521da177e4SLinus Torvalds #define SETB_PCIX_133MHZ_PM 0x54 1531da177e4SLinus Torvalds #define SETB_PCIX_66MHZ_EM 0x55 1541da177e4SLinus Torvalds #define SETB_PCIX_100MHZ_EM 0x56 1551da177e4SLinus Torvalds #define SETB_PCIX_133MHZ_EM 0x57 1561da177e4SLinus Torvalds #define SETB_PCIX_66MHZ_266 0x58 1571da177e4SLinus Torvalds #define SETB_PCIX_100MHZ_266 0x59 1581da177e4SLinus Torvalds #define SETB_PCIX_133MHZ_266 0x5a 1591da177e4SLinus Torvalds #define SETB_PCIX_66MHZ_533 0x5b 1601da177e4SLinus Torvalds #define SETB_PCIX_100MHZ_533 0x5c 1611da177e4SLinus Torvalds #define SETB_PCIX_133MHZ_533 0x5d 1624085399dSKenji Kaneshige #define SETB_RESERVED1 0x5e 1634085399dSKenji Kaneshige #define SETB_RESERVED2 0x5f 1641da177e4SLinus Torvalds 1654085399dSKenji Kaneshige /* 1664085399dSKenji Kaneshige * SHPC controller command error code 1674085399dSKenji Kaneshige */ 1681da177e4SLinus Torvalds #define SWITCH_OPEN 0x1 1691da177e4SLinus Torvalds #define INVALID_CMD 0x2 1701da177e4SLinus Torvalds #define INVALID_SPEED_MODE 0x4 1711da177e4SLinus Torvalds 1724085399dSKenji Kaneshige /* 1734085399dSKenji Kaneshige * For accessing SHPC Working Register Set via PCI Configuration Space 1744085399dSKenji Kaneshige */ 1751da177e4SLinus Torvalds #define DWORD_SELECT 0x2 1761da177e4SLinus Torvalds #define DWORD_DATA 0x4 1771da177e4SLinus Torvalds 1781da177e4SLinus Torvalds /* Field Offset in Logical Slot Register - byte boundary */ 1791da177e4SLinus Torvalds #define SLOT_EVENT_LATCH 0x2 1801da177e4SLinus Torvalds #define SLOT_SERR_INT_MASK 0x3 1811da177e4SLinus Torvalds 18282d5f4aaSKenji Kaneshige static atomic_t shpchp_num_controllers = ATOMIC_INIT(0); 18382d5f4aaSKenji Kaneshige 1847d12e780SDavid Howells static irqreturn_t shpc_isr(int irq, void *dev_id); 1850abe68ceSKenji Kaneshige static void start_int_poll_timer(struct controller *ctrl, int sec); 186d29aaddaSKenji Kaneshige static int hpc_check_cmd_status(struct controller *ctrl); 1871da177e4SLinus Torvalds 18875d97c59SKenji Kaneshige static inline u8 shpc_readb(struct controller *ctrl, int reg) 18975d97c59SKenji Kaneshige { 1900abe68ceSKenji Kaneshige return readb(ctrl->creg + reg); 19175d97c59SKenji Kaneshige } 19275d97c59SKenji Kaneshige 19375d97c59SKenji Kaneshige static inline void shpc_writeb(struct controller *ctrl, int reg, u8 val) 19475d97c59SKenji Kaneshige { 1950abe68ceSKenji Kaneshige writeb(val, ctrl->creg + reg); 19675d97c59SKenji Kaneshige } 19775d97c59SKenji Kaneshige 19875d97c59SKenji Kaneshige static inline u16 shpc_readw(struct controller *ctrl, int reg) 19975d97c59SKenji Kaneshige { 2000abe68ceSKenji Kaneshige return readw(ctrl->creg + reg); 20175d97c59SKenji Kaneshige } 20275d97c59SKenji Kaneshige 20375d97c59SKenji Kaneshige static inline void shpc_writew(struct controller *ctrl, int reg, u16 val) 20475d97c59SKenji Kaneshige { 2050abe68ceSKenji Kaneshige writew(val, ctrl->creg + reg); 20675d97c59SKenji Kaneshige } 20775d97c59SKenji Kaneshige 20875d97c59SKenji Kaneshige static inline u32 shpc_readl(struct controller *ctrl, int reg) 20975d97c59SKenji Kaneshige { 2100abe68ceSKenji Kaneshige return readl(ctrl->creg + reg); 21175d97c59SKenji Kaneshige } 21275d97c59SKenji Kaneshige 21375d97c59SKenji Kaneshige static inline void shpc_writel(struct controller *ctrl, int reg, u32 val) 21475d97c59SKenji Kaneshige { 2150abe68ceSKenji Kaneshige writel(val, ctrl->creg + reg); 21675d97c59SKenji Kaneshige } 21775d97c59SKenji Kaneshige 21875d97c59SKenji Kaneshige static inline int shpc_indirect_read(struct controller *ctrl, int index, 21975d97c59SKenji Kaneshige u32 *value) 22075d97c59SKenji Kaneshige { 22175d97c59SKenji Kaneshige int rc; 22275d97c59SKenji Kaneshige u32 cap_offset = ctrl->cap_offset; 22375d97c59SKenji Kaneshige struct pci_dev *pdev = ctrl->pci_dev; 22475d97c59SKenji Kaneshige 22575d97c59SKenji Kaneshige rc = pci_write_config_byte(pdev, cap_offset + DWORD_SELECT, index); 22675d97c59SKenji Kaneshige if (rc) 22775d97c59SKenji Kaneshige return rc; 22875d97c59SKenji Kaneshige return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value); 22975d97c59SKenji Kaneshige } 23075d97c59SKenji Kaneshige 231f4263957SKenji Kaneshige /* 232f4263957SKenji Kaneshige * This is the interrupt polling timeout function. 233f4263957SKenji Kaneshige */ 2340abe68ceSKenji Kaneshige static void int_poll_timeout(unsigned long data) 2351da177e4SLinus Torvalds { 2360abe68ceSKenji Kaneshige struct controller *ctrl = (struct controller *)data; 2371da177e4SLinus Torvalds 2381da177e4SLinus Torvalds /* Poll for interrupt events. regs == NULL => polling */ 2390abe68ceSKenji Kaneshige shpc_isr(0, ctrl); 2401da177e4SLinus Torvalds 2410abe68ceSKenji Kaneshige init_timer(&ctrl->poll_timer); 2421da177e4SLinus Torvalds if (!shpchp_poll_time) 243f4263957SKenji Kaneshige shpchp_poll_time = 2; /* default polling interval is 2 sec */ 2441da177e4SLinus Torvalds 2450abe68ceSKenji Kaneshige start_int_poll_timer(ctrl, shpchp_poll_time); 2461da177e4SLinus Torvalds } 2471da177e4SLinus Torvalds 248f4263957SKenji Kaneshige /* 249f4263957SKenji Kaneshige * This function starts the interrupt polling timer. 250f4263957SKenji Kaneshige */ 2510abe68ceSKenji Kaneshige static void start_int_poll_timer(struct controller *ctrl, int sec) 2521da177e4SLinus Torvalds { 253f4263957SKenji Kaneshige /* Clamp to sane value */ 254f4263957SKenji Kaneshige if ((sec <= 0) || (sec > 60)) 255f4263957SKenji Kaneshige sec = 2; 2561da177e4SLinus Torvalds 2570abe68ceSKenji Kaneshige ctrl->poll_timer.function = &int_poll_timeout; 2580abe68ceSKenji Kaneshige ctrl->poll_timer.data = (unsigned long)ctrl; 2590abe68ceSKenji Kaneshige ctrl->poll_timer.expires = jiffies + sec * HZ; 2600abe68ceSKenji Kaneshige add_timer(&ctrl->poll_timer); 2611da177e4SLinus Torvalds } 2621da177e4SLinus Torvalds 263d1729cceSKenji Kaneshige static inline int is_ctrl_busy(struct controller *ctrl) 264d1729cceSKenji Kaneshige { 265d1729cceSKenji Kaneshige u16 cmd_status = shpc_readw(ctrl, CMD_STATUS); 266d1729cceSKenji Kaneshige return cmd_status & 0x1; 267d1729cceSKenji Kaneshige } 268d1729cceSKenji Kaneshige 269b4a1efffSKenji Kaneshige /* 270b4a1efffSKenji Kaneshige * Returns 1 if SHPC finishes executing a command within 1 sec, 271b4a1efffSKenji Kaneshige * otherwise returns 0. 272b4a1efffSKenji Kaneshige */ 273b4a1efffSKenji Kaneshige static inline int shpc_poll_ctrl_busy(struct controller *ctrl) 274b4a1efffSKenji Kaneshige { 275b4a1efffSKenji Kaneshige int i; 276b4a1efffSKenji Kaneshige 277d1729cceSKenji Kaneshige if (!is_ctrl_busy(ctrl)) 278b4a1efffSKenji Kaneshige return 1; 279b4a1efffSKenji Kaneshige 280b4a1efffSKenji Kaneshige /* Check every 0.1 sec for a total of 1 sec */ 281b4a1efffSKenji Kaneshige for (i = 0; i < 10; i++) { 282b4a1efffSKenji Kaneshige msleep(100); 283d1729cceSKenji Kaneshige if (!is_ctrl_busy(ctrl)) 284b4a1efffSKenji Kaneshige return 1; 285b4a1efffSKenji Kaneshige } 286b4a1efffSKenji Kaneshige 287b4a1efffSKenji Kaneshige return 0; 288b4a1efffSKenji Kaneshige } 289b4a1efffSKenji Kaneshige 290bd62e271SKenji Kaneshige static inline int shpc_wait_cmd(struct controller *ctrl) 291bd62e271SKenji Kaneshige { 292bd62e271SKenji Kaneshige int retval = 0; 293b4a1efffSKenji Kaneshige unsigned long timeout = msecs_to_jiffies(1000); 294b4a1efffSKenji Kaneshige int rc; 295b4a1efffSKenji Kaneshige 296b4a1efffSKenji Kaneshige if (shpchp_poll_mode) 297b4a1efffSKenji Kaneshige rc = shpc_poll_ctrl_busy(ctrl); 298b4a1efffSKenji Kaneshige else 299b4a1efffSKenji Kaneshige rc = wait_event_interruptible_timeout(ctrl->queue, 3006aa562c2SKenji Kaneshige !is_ctrl_busy(ctrl), timeout); 301d1729cceSKenji Kaneshige if (!rc && is_ctrl_busy(ctrl)) { 302bd62e271SKenji Kaneshige retval = -EIO; 303f98ca311STaku Izumi ctrl_err(ctrl, "Command not completed in 1000 msec\n"); 304bd62e271SKenji Kaneshige } else if (rc < 0) { 305bd62e271SKenji Kaneshige retval = -EINTR; 306f98ca311STaku Izumi ctrl_info(ctrl, "Command was interrupted by a signal\n"); 307bd62e271SKenji Kaneshige } 308bd62e271SKenji Kaneshige 309bd62e271SKenji Kaneshige return retval; 310bd62e271SKenji Kaneshige } 311bd62e271SKenji Kaneshige 3121da177e4SLinus Torvalds static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) 3131da177e4SLinus Torvalds { 31475d97c59SKenji Kaneshige struct controller *ctrl = slot->ctrl; 3151da177e4SLinus Torvalds u16 cmd_status; 3161da177e4SLinus Torvalds int retval = 0; 3171da177e4SLinus Torvalds u16 temp_word; 3181da177e4SLinus Torvalds 319d29aaddaSKenji Kaneshige mutex_lock(&slot->ctrl->cmd_lock); 320d29aaddaSKenji Kaneshige 321b4a1efffSKenji Kaneshige if (!shpc_poll_ctrl_busy(ctrl)) { 3221da177e4SLinus Torvalds /* After 1 sec and and the controller is still busy */ 323be7bce25STaku Izumi ctrl_err(ctrl, "Controller is still busy after 1 sec\n"); 324d29aaddaSKenji Kaneshige retval = -EBUSY; 325d29aaddaSKenji Kaneshige goto out; 3261da177e4SLinus Torvalds } 3271da177e4SLinus Torvalds 3281da177e4SLinus Torvalds ++t_slot; 3291da177e4SLinus Torvalds temp_word = (t_slot << 8) | (cmd & 0xFF); 330f98ca311STaku Izumi ctrl_dbg(ctrl, "%s: t_slot %x cmd %x\n", __func__, t_slot, cmd); 3311da177e4SLinus Torvalds 3321da177e4SLinus Torvalds /* To make sure the Controller Busy bit is 0 before we send out the 3331da177e4SLinus Torvalds * command. 3341da177e4SLinus Torvalds */ 33575d97c59SKenji Kaneshige shpc_writew(ctrl, CMD, temp_word); 3361da177e4SLinus Torvalds 337bd62e271SKenji Kaneshige /* 338bd62e271SKenji Kaneshige * Wait for command completion. 339bd62e271SKenji Kaneshige */ 340bd62e271SKenji Kaneshige retval = shpc_wait_cmd(slot->ctrl); 341d29aaddaSKenji Kaneshige if (retval) 342d29aaddaSKenji Kaneshige goto out; 343d29aaddaSKenji Kaneshige 344d29aaddaSKenji Kaneshige cmd_status = hpc_check_cmd_status(slot->ctrl); 345d29aaddaSKenji Kaneshige if (cmd_status) { 346be7bce25STaku Izumi ctrl_err(ctrl, 347be7bce25STaku Izumi "Failed to issued command 0x%x (error code = %d)\n", 348be7bce25STaku Izumi cmd, cmd_status); 349d29aaddaSKenji Kaneshige retval = -EIO; 350d29aaddaSKenji Kaneshige } 351d29aaddaSKenji Kaneshige out: 352d29aaddaSKenji Kaneshige mutex_unlock(&slot->ctrl->cmd_lock); 3531da177e4SLinus Torvalds return retval; 3541da177e4SLinus Torvalds } 3551da177e4SLinus Torvalds 3561da177e4SLinus Torvalds static int hpc_check_cmd_status(struct controller *ctrl) 3571da177e4SLinus Torvalds { 3581da177e4SLinus Torvalds int retval = 0; 3591555b33dSKenji Kaneshige u16 cmd_status = shpc_readw(ctrl, CMD_STATUS) & 0x000F; 3601da177e4SLinus Torvalds 3611da177e4SLinus Torvalds switch (cmd_status >> 1) { 3621da177e4SLinus Torvalds case 0: 3631da177e4SLinus Torvalds retval = 0; 3641da177e4SLinus Torvalds break; 3651da177e4SLinus Torvalds case 1: 3661da177e4SLinus Torvalds retval = SWITCH_OPEN; 367be7bce25STaku Izumi ctrl_err(ctrl, "Switch opened!\n"); 3681da177e4SLinus Torvalds break; 3691da177e4SLinus Torvalds case 2: 3701da177e4SLinus Torvalds retval = INVALID_CMD; 371be7bce25STaku Izumi ctrl_err(ctrl, "Invalid HPC command!\n"); 3721da177e4SLinus Torvalds break; 3731da177e4SLinus Torvalds case 4: 3741da177e4SLinus Torvalds retval = INVALID_SPEED_MODE; 375be7bce25STaku Izumi ctrl_err(ctrl, "Invalid bus speed/mode!\n"); 3761da177e4SLinus Torvalds break; 3771da177e4SLinus Torvalds default: 3781da177e4SLinus Torvalds retval = cmd_status; 3791da177e4SLinus Torvalds } 3801da177e4SLinus Torvalds 3811da177e4SLinus Torvalds return retval; 3821da177e4SLinus Torvalds } 3831da177e4SLinus Torvalds 3841da177e4SLinus Torvalds 3851da177e4SLinus Torvalds static int hpc_get_attention_status(struct slot *slot, u8 *status) 3861da177e4SLinus Torvalds { 38775d97c59SKenji Kaneshige struct controller *ctrl = slot->ctrl; 3881555b33dSKenji Kaneshige u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); 3891555b33dSKenji Kaneshige u8 state = (slot_reg & ATN_LED_STATE_MASK) >> ATN_LED_STATE_SHIFT; 3901da177e4SLinus Torvalds 3915858759cSKenji Kaneshige switch (state) { 3925858759cSKenji Kaneshige case ATN_LED_STATE_ON: 3931da177e4SLinus Torvalds *status = 1; /* On */ 3941da177e4SLinus Torvalds break; 3955858759cSKenji Kaneshige case ATN_LED_STATE_BLINK: 3961da177e4SLinus Torvalds *status = 2; /* Blink */ 3971da177e4SLinus Torvalds break; 3985858759cSKenji Kaneshige case ATN_LED_STATE_OFF: 3991da177e4SLinus Torvalds *status = 0; /* Off */ 4001da177e4SLinus Torvalds break; 4011da177e4SLinus Torvalds default: 4025858759cSKenji Kaneshige *status = 0xFF; /* Reserved */ 4031da177e4SLinus Torvalds break; 4041da177e4SLinus Torvalds } 4051da177e4SLinus Torvalds 4061da177e4SLinus Torvalds return 0; 4071da177e4SLinus Torvalds } 4081da177e4SLinus Torvalds 4091da177e4SLinus Torvalds static int hpc_get_power_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)); 4131555b33dSKenji Kaneshige u8 state = (slot_reg & SLOT_STATE_MASK) >> SLOT_STATE_SHIFT; 4141da177e4SLinus Torvalds 4155858759cSKenji Kaneshige switch (state) { 4165858759cSKenji Kaneshige case SLOT_STATE_PWRONLY: 4171da177e4SLinus Torvalds *status = 2; /* Powered only */ 4181da177e4SLinus Torvalds break; 4195858759cSKenji Kaneshige case SLOT_STATE_ENABLED: 4201da177e4SLinus Torvalds *status = 1; /* Enabled */ 4211da177e4SLinus Torvalds break; 4225858759cSKenji Kaneshige case SLOT_STATE_DISABLED: 4231da177e4SLinus Torvalds *status = 0; /* Disabled */ 4241da177e4SLinus Torvalds break; 4251da177e4SLinus Torvalds default: 4265858759cSKenji Kaneshige *status = 0xFF; /* Reserved */ 4271da177e4SLinus Torvalds break; 4281da177e4SLinus Torvalds } 4291da177e4SLinus Torvalds 4305858759cSKenji Kaneshige return 0; 4311da177e4SLinus Torvalds } 4321da177e4SLinus Torvalds 4331da177e4SLinus Torvalds 4341da177e4SLinus Torvalds static int hpc_get_latch_status(struct slot *slot, u8 *status) 4351da177e4SLinus Torvalds { 43675d97c59SKenji Kaneshige struct controller *ctrl = slot->ctrl; 4371555b33dSKenji Kaneshige u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); 4381da177e4SLinus Torvalds 4395858759cSKenji Kaneshige *status = !!(slot_reg & MRL_SENSOR); /* 0 -> close; 1 -> open */ 4401da177e4SLinus Torvalds 4411da177e4SLinus Torvalds return 0; 4421da177e4SLinus Torvalds } 4431da177e4SLinus Torvalds 4441da177e4SLinus Torvalds static int hpc_get_adapter_status(struct slot *slot, u8 *status) 4451da177e4SLinus Torvalds { 44675d97c59SKenji Kaneshige struct controller *ctrl = slot->ctrl; 4471555b33dSKenji Kaneshige u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); 4481555b33dSKenji Kaneshige u8 state = (slot_reg & PRSNT_MASK) >> PRSNT_SHIFT; 4491da177e4SLinus Torvalds 4505858759cSKenji Kaneshige *status = (state != 0x3) ? 1 : 0; 4511da177e4SLinus Torvalds 4521da177e4SLinus Torvalds return 0; 4531da177e4SLinus Torvalds } 4541da177e4SLinus Torvalds 4551da177e4SLinus Torvalds static int hpc_get_prog_int(struct slot *slot, u8 *prog_int) 4561da177e4SLinus Torvalds { 45775d97c59SKenji Kaneshige struct controller *ctrl = slot->ctrl; 4581da177e4SLinus Torvalds 45975d97c59SKenji Kaneshige *prog_int = shpc_readb(ctrl, PROG_INTERFACE); 4601da177e4SLinus Torvalds 4611da177e4SLinus Torvalds return 0; 4621da177e4SLinus Torvalds } 4631da177e4SLinus Torvalds 4641da177e4SLinus Torvalds static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) 4651da177e4SLinus Torvalds { 4661da177e4SLinus Torvalds int retval = 0; 46775d97c59SKenji Kaneshige struct controller *ctrl = slot->ctrl; 4682b34da7eSKenji Kaneshige u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); 4695858759cSKenji Kaneshige u8 m66_cap = !!(slot_reg & MHZ66_CAP); 470795eb5c4SKenji Kaneshige u8 pi, pcix_cap; 4711da177e4SLinus Torvalds 472795eb5c4SKenji Kaneshige if ((retval = hpc_get_prog_int(slot, &pi))) 473795eb5c4SKenji Kaneshige return retval; 474795eb5c4SKenji Kaneshige 475795eb5c4SKenji Kaneshige switch (pi) { 476795eb5c4SKenji Kaneshige case 1: 477795eb5c4SKenji Kaneshige pcix_cap = (slot_reg & PCIX_CAP_MASK_PI1) >> PCIX_CAP_SHIFT; 478795eb5c4SKenji Kaneshige break; 479795eb5c4SKenji Kaneshige case 2: 480795eb5c4SKenji Kaneshige pcix_cap = (slot_reg & PCIX_CAP_MASK_PI2) >> PCIX_CAP_SHIFT; 481795eb5c4SKenji Kaneshige break; 482795eb5c4SKenji Kaneshige default: 483795eb5c4SKenji Kaneshige return -ENODEV; 484795eb5c4SKenji Kaneshige } 485795eb5c4SKenji Kaneshige 486f98ca311STaku Izumi ctrl_dbg(ctrl, "%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n", 48766bef8c0SHarvey Harrison __func__, slot_reg, pcix_cap, m66_cap); 4881da177e4SLinus Torvalds 4891da177e4SLinus Torvalds switch (pcix_cap) { 4900afabe90SKenji Kaneshige case 0x0: 4911da177e4SLinus Torvalds *value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; 4921da177e4SLinus Torvalds break; 4930afabe90SKenji Kaneshige case 0x1: 4941da177e4SLinus Torvalds *value = PCI_SPEED_66MHz_PCIX; 4951da177e4SLinus Torvalds break; 4960afabe90SKenji Kaneshige case 0x3: 4971da177e4SLinus Torvalds *value = PCI_SPEED_133MHz_PCIX; 4981da177e4SLinus Torvalds break; 4990afabe90SKenji Kaneshige case 0x4: 5001da177e4SLinus Torvalds *value = PCI_SPEED_133MHz_PCIX_266; 5011da177e4SLinus Torvalds break; 5020afabe90SKenji Kaneshige case 0x5: 5031da177e4SLinus Torvalds *value = PCI_SPEED_133MHz_PCIX_533; 5041da177e4SLinus Torvalds break; 5050afabe90SKenji Kaneshige case 0x2: 5061da177e4SLinus Torvalds default: 5071da177e4SLinus Torvalds *value = PCI_SPEED_UNKNOWN; 5081da177e4SLinus Torvalds retval = -ENODEV; 5091da177e4SLinus Torvalds break; 5101da177e4SLinus Torvalds } 5111da177e4SLinus Torvalds 512f98ca311STaku Izumi ctrl_dbg(ctrl, "Adapter speed = %d\n", *value); 5131da177e4SLinus Torvalds return retval; 5141da177e4SLinus Torvalds } 5151da177e4SLinus Torvalds 5161da177e4SLinus Torvalds static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode) 5171da177e4SLinus Torvalds { 5181da177e4SLinus Torvalds int retval = 0; 5191555b33dSKenji Kaneshige struct controller *ctrl = slot->ctrl; 5201555b33dSKenji Kaneshige u16 sec_bus_status = shpc_readw(ctrl, SEC_BUS_CONFIG); 5211555b33dSKenji Kaneshige u8 pi = shpc_readb(ctrl, PROG_INTERFACE); 5221da177e4SLinus Torvalds 5231da177e4SLinus Torvalds if (pi == 2) { 52487d6c559SKenji Kaneshige *mode = (sec_bus_status & 0x0100) >> 8; 5251da177e4SLinus Torvalds } else { 5261da177e4SLinus Torvalds retval = -1; 5271da177e4SLinus Torvalds } 5281da177e4SLinus Torvalds 529f98ca311STaku Izumi ctrl_dbg(ctrl, "Mode 1 ECC cap = %d\n", *mode); 5301da177e4SLinus Torvalds return retval; 5311da177e4SLinus Torvalds } 5321da177e4SLinus Torvalds 5331da177e4SLinus Torvalds static int hpc_query_power_fault(struct slot * slot) 5341da177e4SLinus Torvalds { 53575d97c59SKenji Kaneshige struct controller *ctrl = slot->ctrl; 5361555b33dSKenji Kaneshige u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); 5371da177e4SLinus Torvalds 5381da177e4SLinus Torvalds /* Note: Logic 0 => fault */ 5395858759cSKenji Kaneshige return !(slot_reg & POWER_FAULT); 5401da177e4SLinus Torvalds } 5411da177e4SLinus Torvalds 5421da177e4SLinus Torvalds static int hpc_set_attention_status(struct slot *slot, u8 value) 5431da177e4SLinus Torvalds { 5441da177e4SLinus Torvalds u8 slot_cmd = 0; 5451da177e4SLinus Torvalds 5461da177e4SLinus Torvalds switch (value) { 5471da177e4SLinus Torvalds case 0 : 5484085399dSKenji Kaneshige slot_cmd = SET_ATTN_OFF; /* OFF */ 5491da177e4SLinus Torvalds break; 5501da177e4SLinus Torvalds case 1: 5514085399dSKenji Kaneshige slot_cmd = SET_ATTN_ON; /* ON */ 5521da177e4SLinus Torvalds break; 5531da177e4SLinus Torvalds case 2: 5544085399dSKenji Kaneshige slot_cmd = SET_ATTN_BLINK; /* BLINK */ 5551da177e4SLinus Torvalds break; 5561da177e4SLinus Torvalds default: 5571da177e4SLinus Torvalds return -1; 5581da177e4SLinus Torvalds } 5591da177e4SLinus Torvalds 560d4fbf600SKenji Kaneshige return shpc_write_cmd(slot, slot->hp_slot, slot_cmd); 5611da177e4SLinus Torvalds } 5621da177e4SLinus Torvalds 5631da177e4SLinus Torvalds 5641da177e4SLinus Torvalds static void hpc_set_green_led_on(struct slot *slot) 5651da177e4SLinus Torvalds { 5664085399dSKenji Kaneshige shpc_write_cmd(slot, slot->hp_slot, SET_PWR_ON); 5671da177e4SLinus Torvalds } 5681da177e4SLinus Torvalds 5691da177e4SLinus Torvalds static void hpc_set_green_led_off(struct slot *slot) 5701da177e4SLinus Torvalds { 5714085399dSKenji Kaneshige shpc_write_cmd(slot, slot->hp_slot, SET_PWR_OFF); 5721da177e4SLinus Torvalds } 5731da177e4SLinus Torvalds 5741da177e4SLinus Torvalds static void hpc_set_green_led_blink(struct slot *slot) 5751da177e4SLinus Torvalds { 5764085399dSKenji Kaneshige shpc_write_cmd(slot, slot->hp_slot, SET_PWR_BLINK); 5771da177e4SLinus Torvalds } 5781da177e4SLinus Torvalds 5791da177e4SLinus Torvalds static void hpc_release_ctlr(struct controller *ctrl) 5801da177e4SLinus Torvalds { 581f7391f53SKenji Kaneshige int i; 582d49f2c49SKenji Kaneshige u32 slot_reg, serr_int; 5831da177e4SLinus Torvalds 584f7391f53SKenji Kaneshige /* 585795eb5c4SKenji Kaneshige * Mask event interrupts and SERRs of all slots 586f7391f53SKenji Kaneshige */ 587795eb5c4SKenji Kaneshige for (i = 0; i < ctrl->num_slots; i++) { 588795eb5c4SKenji Kaneshige slot_reg = shpc_readl(ctrl, SLOT_REG(i)); 589795eb5c4SKenji Kaneshige slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK | 590795eb5c4SKenji Kaneshige BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK | 591795eb5c4SKenji Kaneshige CON_PFAULT_INTR_MASK | MRL_CHANGE_SERR_MASK | 592795eb5c4SKenji Kaneshige CON_PFAULT_SERR_MASK); 593795eb5c4SKenji Kaneshige slot_reg &= ~SLOT_REG_RSVDZ_MASK; 594795eb5c4SKenji Kaneshige shpc_writel(ctrl, SLOT_REG(i), slot_reg); 595795eb5c4SKenji Kaneshige } 596f7391f53SKenji Kaneshige 597f7391f53SKenji Kaneshige cleanup_slots(ctrl); 598f7391f53SKenji Kaneshige 599d49f2c49SKenji Kaneshige /* 6003609801eSJoe Perches * Mask SERR and System Interrupt generation 601d49f2c49SKenji Kaneshige */ 602d49f2c49SKenji Kaneshige serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE); 603d49f2c49SKenji Kaneshige serr_int |= (GLOBAL_INTR_MASK | GLOBAL_SERR_MASK | 604d49f2c49SKenji Kaneshige COMMAND_INTR_MASK | ARBITER_SERR_MASK); 605d49f2c49SKenji Kaneshige serr_int &= ~SERR_INTR_RSVDZ_MASK; 606d49f2c49SKenji Kaneshige shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); 607d49f2c49SKenji Kaneshige 6080abe68ceSKenji Kaneshige if (shpchp_poll_mode) 6090abe68ceSKenji Kaneshige del_timer(&ctrl->poll_timer); 6100abe68ceSKenji Kaneshige else { 6110abe68ceSKenji Kaneshige free_irq(ctrl->pci_dev->irq, ctrl); 6120abe68ceSKenji Kaneshige pci_disable_msi(ctrl->pci_dev); 6131da177e4SLinus Torvalds } 614f7391f53SKenji Kaneshige 6150abe68ceSKenji Kaneshige iounmap(ctrl->creg); 6160455986cSKenji Kaneshige release_mem_region(ctrl->mmio_base, ctrl->mmio_size); 6171da177e4SLinus Torvalds 61882d5f4aaSKenji Kaneshige /* 61982d5f4aaSKenji Kaneshige * If this is the last controller to be released, destroy the 62082d5f4aaSKenji Kaneshige * shpchpd work queue 62182d5f4aaSKenji Kaneshige */ 62282d5f4aaSKenji Kaneshige if (atomic_dec_and_test(&shpchp_num_controllers)) 62382d5f4aaSKenji Kaneshige destroy_workqueue(shpchp_wq); 6241da177e4SLinus Torvalds } 6251da177e4SLinus Torvalds 6261da177e4SLinus Torvalds static int hpc_power_on_slot(struct slot * slot) 6271da177e4SLinus Torvalds { 628d4fbf600SKenji Kaneshige int retval; 6291da177e4SLinus Torvalds 6304085399dSKenji Kaneshige retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_PWR); 6311555b33dSKenji Kaneshige if (retval) 632f98ca311STaku Izumi ctrl_err(slot->ctrl, "%s: Write command failed!\n", __func__); 6331555b33dSKenji Kaneshige 634d4fbf600SKenji Kaneshige return retval; 6351da177e4SLinus Torvalds } 6361da177e4SLinus Torvalds 6371da177e4SLinus Torvalds static int hpc_slot_enable(struct slot * slot) 6381da177e4SLinus Torvalds { 639d4fbf600SKenji Kaneshige int retval; 6401da177e4SLinus Torvalds 6414085399dSKenji Kaneshige /* Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */ 6424085399dSKenji Kaneshige retval = shpc_write_cmd(slot, slot->hp_slot, 6434085399dSKenji Kaneshige SET_SLOT_ENABLE | SET_PWR_BLINK | SET_ATTN_OFF); 6441555b33dSKenji Kaneshige if (retval) 645f98ca311STaku Izumi ctrl_err(slot->ctrl, "%s: Write command failed!\n", __func__); 6461da177e4SLinus Torvalds 6471555b33dSKenji Kaneshige return retval; 6481da177e4SLinus Torvalds } 6491da177e4SLinus Torvalds 6501da177e4SLinus Torvalds static int hpc_slot_disable(struct slot * slot) 6511da177e4SLinus Torvalds { 652d4fbf600SKenji Kaneshige int retval; 6531da177e4SLinus Torvalds 6544085399dSKenji Kaneshige /* Slot - Disable, Power Indicator - Off, Attention Indicator - On */ 6554085399dSKenji Kaneshige retval = shpc_write_cmd(slot, slot->hp_slot, 6564085399dSKenji Kaneshige SET_SLOT_DISABLE | SET_PWR_OFF | SET_ATTN_ON); 6571555b33dSKenji Kaneshige if (retval) 658f98ca311STaku Izumi ctrl_err(slot->ctrl, "%s: Write command failed!\n", __func__); 6591da177e4SLinus Torvalds 6601555b33dSKenji Kaneshige return retval; 6611da177e4SLinus Torvalds } 6621da177e4SLinus Torvalds 6631da177e4SLinus Torvalds static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) 6641da177e4SLinus Torvalds { 6650afabe90SKenji Kaneshige int retval; 66675d97c59SKenji Kaneshige struct controller *ctrl = slot->ctrl; 6670afabe90SKenji Kaneshige u8 pi, cmd; 6681da177e4SLinus Torvalds 66975d97c59SKenji Kaneshige pi = shpc_readb(ctrl, PROG_INTERFACE); 6700afabe90SKenji Kaneshige if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX)) 6710afabe90SKenji Kaneshige return -EINVAL; 6721da177e4SLinus Torvalds 6731da177e4SLinus Torvalds switch (value) { 6740afabe90SKenji Kaneshige case PCI_SPEED_33MHz: 6750afabe90SKenji Kaneshige cmd = SETA_PCI_33MHZ; 6761da177e4SLinus Torvalds break; 6770afabe90SKenji Kaneshige case PCI_SPEED_66MHz: 6780afabe90SKenji Kaneshige cmd = SETA_PCI_66MHZ; 6791da177e4SLinus Torvalds break; 6800afabe90SKenji Kaneshige case PCI_SPEED_66MHz_PCIX: 6810afabe90SKenji Kaneshige cmd = SETA_PCIX_66MHZ; 6821da177e4SLinus Torvalds break; 6830afabe90SKenji Kaneshige case PCI_SPEED_100MHz_PCIX: 6840afabe90SKenji Kaneshige cmd = SETA_PCIX_100MHZ; 6851da177e4SLinus Torvalds break; 6860afabe90SKenji Kaneshige case PCI_SPEED_133MHz_PCIX: 6870afabe90SKenji Kaneshige cmd = SETA_PCIX_133MHZ; 6880afabe90SKenji Kaneshige break; 6890afabe90SKenji Kaneshige case PCI_SPEED_66MHz_PCIX_ECC: 6900afabe90SKenji Kaneshige cmd = SETB_PCIX_66MHZ_EM; 6910afabe90SKenji Kaneshige break; 6920afabe90SKenji Kaneshige case PCI_SPEED_100MHz_PCIX_ECC: 6930afabe90SKenji Kaneshige cmd = SETB_PCIX_100MHZ_EM; 6940afabe90SKenji Kaneshige break; 6950afabe90SKenji Kaneshige case PCI_SPEED_133MHz_PCIX_ECC: 6960afabe90SKenji Kaneshige cmd = SETB_PCIX_133MHZ_EM; 6970afabe90SKenji Kaneshige break; 6980afabe90SKenji Kaneshige case PCI_SPEED_66MHz_PCIX_266: 6990afabe90SKenji Kaneshige cmd = SETB_PCIX_66MHZ_266; 7000afabe90SKenji Kaneshige break; 7010afabe90SKenji Kaneshige case PCI_SPEED_100MHz_PCIX_266: 7020afabe90SKenji Kaneshige cmd = SETB_PCIX_100MHZ_266; 7030afabe90SKenji Kaneshige break; 7040afabe90SKenji Kaneshige case PCI_SPEED_133MHz_PCIX_266: 7050afabe90SKenji Kaneshige cmd = SETB_PCIX_133MHZ_266; 7060afabe90SKenji Kaneshige break; 7070afabe90SKenji Kaneshige case PCI_SPEED_66MHz_PCIX_533: 7080afabe90SKenji Kaneshige cmd = SETB_PCIX_66MHZ_533; 7090afabe90SKenji Kaneshige break; 7100afabe90SKenji Kaneshige case PCI_SPEED_100MHz_PCIX_533: 7110afabe90SKenji Kaneshige cmd = SETB_PCIX_100MHZ_533; 7120afabe90SKenji Kaneshige break; 7130afabe90SKenji Kaneshige case PCI_SPEED_133MHz_PCIX_533: 7140afabe90SKenji Kaneshige cmd = SETB_PCIX_133MHZ_533; 7151da177e4SLinus Torvalds break; 7161da177e4SLinus Torvalds default: 7170afabe90SKenji Kaneshige return -EINVAL; 7181da177e4SLinus Torvalds } 7191da177e4SLinus Torvalds 7200afabe90SKenji Kaneshige retval = shpc_write_cmd(slot, 0, cmd); 7210afabe90SKenji Kaneshige if (retval) 722f98ca311STaku Izumi ctrl_err(ctrl, "%s: Write command failed!\n", __func__); 7231da177e4SLinus Torvalds 7241da177e4SLinus Torvalds return retval; 7251da177e4SLinus Torvalds } 7261da177e4SLinus Torvalds 7277d12e780SDavid Howells static irqreturn_t shpc_isr(int irq, void *dev_id) 7281da177e4SLinus Torvalds { 729c4cecc19SKenji Kaneshige struct controller *ctrl = (struct controller *)dev_id; 730c4cecc19SKenji Kaneshige u32 serr_int, slot_reg, intr_loc, intr_loc2; 7311da177e4SLinus Torvalds int hp_slot; 7321da177e4SLinus Torvalds 7331da177e4SLinus Torvalds /* Check to see if it was our interrupt */ 73475d97c59SKenji Kaneshige intr_loc = shpc_readl(ctrl, INTR_LOC); 7351da177e4SLinus Torvalds if (!intr_loc) 7361da177e4SLinus Torvalds return IRQ_NONE; 737c4cecc19SKenji Kaneshige 738f98ca311STaku Izumi ctrl_dbg(ctrl, "%s: intr_loc = %x\n", __func__, intr_loc); 7391da177e4SLinus Torvalds 7401da177e4SLinus Torvalds if(!shpchp_poll_mode) { 741c4cecc19SKenji Kaneshige /* 742c4cecc19SKenji Kaneshige * Mask Global Interrupt Mask - see implementation 743c4cecc19SKenji Kaneshige * note on p. 139 of SHPC spec rev 1.0 744c4cecc19SKenji Kaneshige */ 745c4cecc19SKenji Kaneshige serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE); 746c4cecc19SKenji Kaneshige serr_int |= GLOBAL_INTR_MASK; 747c4cecc19SKenji Kaneshige serr_int &= ~SERR_INTR_RSVDZ_MASK; 748c4cecc19SKenji Kaneshige shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); 7491da177e4SLinus Torvalds 75075d97c59SKenji Kaneshige intr_loc2 = shpc_readl(ctrl, INTR_LOC); 751f98ca311STaku Izumi ctrl_dbg(ctrl, "%s: intr_loc2 = %x\n", __func__, intr_loc2); 7521da177e4SLinus Torvalds } 7531da177e4SLinus Torvalds 754c4cecc19SKenji Kaneshige if (intr_loc & CMD_INTR_PENDING) { 7551da177e4SLinus Torvalds /* 7561da177e4SLinus Torvalds * Command Complete Interrupt Pending 757f467f618SKenji Kaneshige * RO only - clear by writing 1 to the Command Completion 7581da177e4SLinus Torvalds * Detect bit in Controller SERR-INT register 7591da177e4SLinus Torvalds */ 760c4cecc19SKenji Kaneshige serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE); 761c4cecc19SKenji Kaneshige serr_int &= ~SERR_INTR_RSVDZ_MASK; 762c4cecc19SKenji Kaneshige shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); 763c4cecc19SKenji Kaneshige 7641da177e4SLinus Torvalds wake_up_interruptible(&ctrl->queue); 7651da177e4SLinus Torvalds } 7661da177e4SLinus Torvalds 767c4cecc19SKenji Kaneshige if (!(intr_loc & ~CMD_INTR_PENDING)) 768e4e73041SKenji Kaneshige goto out; 7691da177e4SLinus Torvalds 7701da177e4SLinus Torvalds for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { 7711da177e4SLinus Torvalds /* To find out which slot has interrupt pending */ 772c4cecc19SKenji Kaneshige if (!(intr_loc & SLOT_INTR_PENDING(hp_slot))) 773c4cecc19SKenji Kaneshige continue; 774c4cecc19SKenji Kaneshige 775c4cecc19SKenji Kaneshige slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); 776be7bce25STaku Izumi ctrl_dbg(ctrl, "Slot %x with intr, slot register = %x\n", 777be7bce25STaku Izumi hp_slot, slot_reg); 778c4cecc19SKenji Kaneshige 779c4cecc19SKenji Kaneshige if (slot_reg & MRL_CHANGE_DETECTED) 7800abe68ceSKenji Kaneshige shpchp_handle_switch_change(hp_slot, ctrl); 781c4cecc19SKenji Kaneshige 782c4cecc19SKenji Kaneshige if (slot_reg & BUTTON_PRESS_DETECTED) 7830abe68ceSKenji Kaneshige shpchp_handle_attention_button(hp_slot, ctrl); 784c4cecc19SKenji Kaneshige 785c4cecc19SKenji Kaneshige if (slot_reg & PRSNT_CHANGE_DETECTED) 7860abe68ceSKenji Kaneshige shpchp_handle_presence_change(hp_slot, ctrl); 787c4cecc19SKenji Kaneshige 788c4cecc19SKenji Kaneshige if (slot_reg & (ISO_PFAULT_DETECTED | CON_PFAULT_DETECTED)) 7890abe68ceSKenji Kaneshige shpchp_handle_power_fault(hp_slot, ctrl); 7901da177e4SLinus Torvalds 7911da177e4SLinus Torvalds /* Clear all slot events */ 792c4cecc19SKenji Kaneshige slot_reg &= ~SLOT_REG_RSVDZ_MASK; 793c4cecc19SKenji Kaneshige shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); 7941da177e4SLinus Torvalds } 795e4e73041SKenji Kaneshige out: 7961da177e4SLinus Torvalds if (!shpchp_poll_mode) { 7971da177e4SLinus Torvalds /* Unmask Global Interrupt Mask */ 798c4cecc19SKenji Kaneshige serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE); 799c4cecc19SKenji Kaneshige serr_int &= ~(GLOBAL_INTR_MASK | SERR_INTR_RSVDZ_MASK); 800c4cecc19SKenji Kaneshige shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); 8011da177e4SLinus Torvalds } 8021da177e4SLinus Torvalds 8031da177e4SLinus Torvalds return IRQ_HANDLED; 8041da177e4SLinus Torvalds } 8051da177e4SLinus Torvalds 8061da177e4SLinus Torvalds static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) 8071da177e4SLinus Torvalds { 8080afabe90SKenji Kaneshige int retval = 0; 80975d97c59SKenji Kaneshige struct controller *ctrl = slot->ctrl; 8101da177e4SLinus Torvalds enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; 81175d97c59SKenji Kaneshige u8 pi = shpc_readb(ctrl, PROG_INTERFACE); 81275d97c59SKenji Kaneshige u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1); 81375d97c59SKenji Kaneshige u32 slot_avail2 = shpc_readl(ctrl, SLOT_AVAIL2); 8141da177e4SLinus Torvalds 8151da177e4SLinus Torvalds if (pi == 2) { 8166558b6abSKenji Kaneshige if (slot_avail2 & SLOT_133MHZ_PCIX_533) 8170afabe90SKenji Kaneshige bus_speed = PCI_SPEED_133MHz_PCIX_533; 8186558b6abSKenji Kaneshige else if (slot_avail2 & SLOT_100MHZ_PCIX_533) 8190afabe90SKenji Kaneshige bus_speed = PCI_SPEED_100MHz_PCIX_533; 8206558b6abSKenji Kaneshige else if (slot_avail2 & SLOT_66MHZ_PCIX_533) 8210afabe90SKenji Kaneshige bus_speed = PCI_SPEED_66MHz_PCIX_533; 8226558b6abSKenji Kaneshige else if (slot_avail2 & SLOT_133MHZ_PCIX_266) 8230afabe90SKenji Kaneshige bus_speed = PCI_SPEED_133MHz_PCIX_266; 8246558b6abSKenji Kaneshige else if (slot_avail2 & SLOT_100MHZ_PCIX_266) 8250afabe90SKenji Kaneshige bus_speed = PCI_SPEED_100MHz_PCIX_266; 8266558b6abSKenji Kaneshige else if (slot_avail2 & SLOT_66MHZ_PCIX_266) 8270afabe90SKenji Kaneshige bus_speed = PCI_SPEED_66MHz_PCIX_266; 8280afabe90SKenji Kaneshige } 8290afabe90SKenji Kaneshige 8300afabe90SKenji Kaneshige if (bus_speed == PCI_SPEED_UNKNOWN) { 8316558b6abSKenji Kaneshige if (slot_avail1 & SLOT_133MHZ_PCIX) 8320afabe90SKenji Kaneshige bus_speed = PCI_SPEED_133MHz_PCIX; 8336558b6abSKenji Kaneshige else if (slot_avail1 & SLOT_100MHZ_PCIX) 8340afabe90SKenji Kaneshige bus_speed = PCI_SPEED_100MHz_PCIX; 8356558b6abSKenji Kaneshige else if (slot_avail1 & SLOT_66MHZ_PCIX) 8360afabe90SKenji Kaneshige bus_speed = PCI_SPEED_66MHz_PCIX; 8376558b6abSKenji Kaneshige else if (slot_avail2 & SLOT_66MHZ) 8380afabe90SKenji Kaneshige bus_speed = PCI_SPEED_66MHz; 8396558b6abSKenji Kaneshige else if (slot_avail1 & SLOT_33MHZ) 8400afabe90SKenji Kaneshige bus_speed = PCI_SPEED_33MHz; 8410afabe90SKenji Kaneshige else 8420afabe90SKenji Kaneshige retval = -ENODEV; 8431da177e4SLinus Torvalds } 8441da177e4SLinus Torvalds 8451da177e4SLinus Torvalds *value = bus_speed; 846f98ca311STaku Izumi ctrl_dbg(ctrl, "Max bus speed = %d\n", bus_speed); 8471555b33dSKenji Kaneshige 8481da177e4SLinus Torvalds return retval; 8491da177e4SLinus Torvalds } 8501da177e4SLinus Torvalds 8511da177e4SLinus Torvalds static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value) 8521da177e4SLinus Torvalds { 8530afabe90SKenji Kaneshige int retval = 0; 85475d97c59SKenji Kaneshige struct controller *ctrl = slot->ctrl; 8551da177e4SLinus Torvalds enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; 85675d97c59SKenji Kaneshige u16 sec_bus_reg = shpc_readw(ctrl, SEC_BUS_CONFIG); 85775d97c59SKenji Kaneshige u8 pi = shpc_readb(ctrl, PROG_INTERFACE); 8580afabe90SKenji Kaneshige u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7); 8591da177e4SLinus Torvalds 8600afabe90SKenji Kaneshige if ((pi == 1) && (speed_mode > 4)) { 8610afabe90SKenji Kaneshige *value = PCI_SPEED_UNKNOWN; 8620afabe90SKenji Kaneshige return -ENODEV; 8631da177e4SLinus Torvalds } 8641da177e4SLinus Torvalds 8650afabe90SKenji Kaneshige switch (speed_mode) { 8660afabe90SKenji Kaneshige case 0x0: 8670afabe90SKenji Kaneshige *value = PCI_SPEED_33MHz; 8681da177e4SLinus Torvalds break; 8690afabe90SKenji Kaneshige case 0x1: 8700afabe90SKenji Kaneshige *value = PCI_SPEED_66MHz; 8711da177e4SLinus Torvalds break; 8720afabe90SKenji Kaneshige case 0x2: 8730afabe90SKenji Kaneshige *value = PCI_SPEED_66MHz_PCIX; 8741da177e4SLinus Torvalds break; 8750afabe90SKenji Kaneshige case 0x3: 8760afabe90SKenji Kaneshige *value = PCI_SPEED_100MHz_PCIX; 8771da177e4SLinus Torvalds break; 8780afabe90SKenji Kaneshige case 0x4: 8790afabe90SKenji Kaneshige *value = PCI_SPEED_133MHz_PCIX; 8801da177e4SLinus Torvalds break; 8810afabe90SKenji Kaneshige case 0x5: 8820afabe90SKenji Kaneshige *value = PCI_SPEED_66MHz_PCIX_ECC; 8831da177e4SLinus Torvalds break; 8840afabe90SKenji Kaneshige case 0x6: 8850afabe90SKenji Kaneshige *value = PCI_SPEED_100MHz_PCIX_ECC; 8861da177e4SLinus Torvalds break; 8870afabe90SKenji Kaneshige case 0x7: 8880afabe90SKenji Kaneshige *value = PCI_SPEED_133MHz_PCIX_ECC; 8891da177e4SLinus Torvalds break; 8900afabe90SKenji Kaneshige case 0x8: 8910afabe90SKenji Kaneshige *value = PCI_SPEED_66MHz_PCIX_266; 8921da177e4SLinus Torvalds break; 8930afabe90SKenji Kaneshige case 0x9: 8940afabe90SKenji Kaneshige *value = PCI_SPEED_100MHz_PCIX_266; 8951da177e4SLinus Torvalds break; 8961da177e4SLinus Torvalds case 0xa: 8970afabe90SKenji Kaneshige *value = PCI_SPEED_133MHz_PCIX_266; 8981da177e4SLinus Torvalds break; 8991da177e4SLinus Torvalds case 0xb: 9000afabe90SKenji Kaneshige *value = PCI_SPEED_66MHz_PCIX_533; 9011da177e4SLinus Torvalds break; 9021da177e4SLinus Torvalds case 0xc: 9030afabe90SKenji Kaneshige *value = PCI_SPEED_100MHz_PCIX_533; 9041da177e4SLinus Torvalds break; 9051da177e4SLinus Torvalds case 0xd: 9060afabe90SKenji Kaneshige *value = PCI_SPEED_133MHz_PCIX_533; 9071da177e4SLinus Torvalds break; 9081da177e4SLinus Torvalds default: 9090afabe90SKenji Kaneshige *value = PCI_SPEED_UNKNOWN; 9100afabe90SKenji Kaneshige retval = -ENODEV; 9111da177e4SLinus Torvalds break; 9121da177e4SLinus Torvalds } 9131da177e4SLinus Torvalds 914f98ca311STaku Izumi ctrl_dbg(ctrl, "Current bus speed = %d\n", bus_speed); 9151da177e4SLinus Torvalds return retval; 9161da177e4SLinus Torvalds } 9171da177e4SLinus Torvalds 9181da177e4SLinus Torvalds static struct hpc_ops shpchp_hpc_ops = { 9191da177e4SLinus Torvalds .power_on_slot = hpc_power_on_slot, 9201da177e4SLinus Torvalds .slot_enable = hpc_slot_enable, 9211da177e4SLinus Torvalds .slot_disable = hpc_slot_disable, 9221da177e4SLinus Torvalds .set_bus_speed_mode = hpc_set_bus_speed_mode, 9231da177e4SLinus Torvalds .set_attention_status = hpc_set_attention_status, 9241da177e4SLinus Torvalds .get_power_status = hpc_get_power_status, 9251da177e4SLinus Torvalds .get_attention_status = hpc_get_attention_status, 9261da177e4SLinus Torvalds .get_latch_status = hpc_get_latch_status, 9271da177e4SLinus Torvalds .get_adapter_status = hpc_get_adapter_status, 9281da177e4SLinus Torvalds 9291da177e4SLinus Torvalds .get_max_bus_speed = hpc_get_max_bus_speed, 9301da177e4SLinus Torvalds .get_cur_bus_speed = hpc_get_cur_bus_speed, 9311da177e4SLinus Torvalds .get_adapter_speed = hpc_get_adapter_speed, 9321da177e4SLinus Torvalds .get_mode1_ECC_cap = hpc_get_mode1_ECC_cap, 9331da177e4SLinus Torvalds .get_prog_int = hpc_get_prog_int, 9341da177e4SLinus Torvalds 9351da177e4SLinus Torvalds .query_power_fault = hpc_query_power_fault, 9361da177e4SLinus Torvalds .green_led_on = hpc_set_green_led_on, 9371da177e4SLinus Torvalds .green_led_off = hpc_set_green_led_off, 9381da177e4SLinus Torvalds .green_led_blink = hpc_set_green_led_blink, 9391da177e4SLinus Torvalds 9401da177e4SLinus Torvalds .release_ctlr = hpc_release_ctlr, 9411da177e4SLinus Torvalds }; 9421da177e4SLinus Torvalds 943ee138334Srajesh.shah@intel.com int shpc_init(struct controller *ctrl, struct pci_dev *pdev) 9441da177e4SLinus Torvalds { 945662a98fbSAmol Lad int rc = -1, num_slots = 0; 9461da177e4SLinus Torvalds u8 hp_slot; 9470455986cSKenji Kaneshige u32 shpc_base_offset; 94875d97c59SKenji Kaneshige u32 tempdword, slot_reg, slot_config; 9491da177e4SLinus Torvalds u8 i; 9501da177e4SLinus Torvalds 9510455986cSKenji Kaneshige ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ 952be7bce25STaku Izumi ctrl_dbg(ctrl, "Hotplug Controller:\n"); 9530455986cSKenji Kaneshige 954ee138334Srajesh.shah@intel.com if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device == 955ee138334Srajesh.shah@intel.com PCI_DEVICE_ID_AMD_GOLAM_7450)) { 9560455986cSKenji Kaneshige /* amd shpc driver doesn't use Base Offset; assume 0 */ 9570455986cSKenji Kaneshige ctrl->mmio_base = pci_resource_start(pdev, 0); 9580455986cSKenji Kaneshige ctrl->mmio_size = pci_resource_len(pdev, 0); 9591da177e4SLinus Torvalds } else { 9600455986cSKenji Kaneshige ctrl->cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC); 9610455986cSKenji Kaneshige if (!ctrl->cap_offset) { 962be7bce25STaku Izumi ctrl_err(ctrl, "Cannot find PCI capability\n"); 9630abe68ceSKenji Kaneshige goto abort; 9641da177e4SLinus Torvalds } 965be7bce25STaku Izumi ctrl_dbg(ctrl, " cap_offset = %x\n", ctrl->cap_offset); 9661da177e4SLinus Torvalds 96775d97c59SKenji Kaneshige rc = shpc_indirect_read(ctrl, 0, &shpc_base_offset); 9681da177e4SLinus Torvalds if (rc) { 969be7bce25STaku Izumi ctrl_err(ctrl, "Cannot read base_offset\n"); 9700abe68ceSKenji Kaneshige goto abort; 9711da177e4SLinus Torvalds } 9721da177e4SLinus Torvalds 97375d97c59SKenji Kaneshige rc = shpc_indirect_read(ctrl, 3, &tempdword); 9741da177e4SLinus Torvalds if (rc) { 975be7bce25STaku Izumi ctrl_err(ctrl, "Cannot read slot config\n"); 9760abe68ceSKenji Kaneshige goto abort; 9771da177e4SLinus Torvalds } 9780455986cSKenji Kaneshige num_slots = tempdword & SLOT_NUM; 979be7bce25STaku Izumi ctrl_dbg(ctrl, " num_slots (indirect) %x\n", num_slots); 9801da177e4SLinus Torvalds 9810455986cSKenji Kaneshige for (i = 0; i < 9 + num_slots; i++) { 98275d97c59SKenji Kaneshige rc = shpc_indirect_read(ctrl, i, &tempdword); 9831da177e4SLinus Torvalds if (rc) { 984be7bce25STaku Izumi ctrl_err(ctrl, 985be7bce25STaku Izumi "Cannot read creg (index = %d)\n", i); 9860abe68ceSKenji Kaneshige goto abort; 9871da177e4SLinus Torvalds } 988be7bce25STaku Izumi ctrl_dbg(ctrl, " offset %d: value %x\n", i, tempdword); 9891da177e4SLinus Torvalds } 9900455986cSKenji Kaneshige 9910455986cSKenji Kaneshige ctrl->mmio_base = 9920455986cSKenji Kaneshige pci_resource_start(pdev, 0) + shpc_base_offset; 9930455986cSKenji Kaneshige ctrl->mmio_size = 0x24 + 0x4 * num_slots; 9941da177e4SLinus Torvalds } 9951da177e4SLinus Torvalds 996f98ca311STaku Izumi ctrl_info(ctrl, "HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", 997f98ca311STaku Izumi pdev->vendor, pdev->device, pdev->subsystem_vendor, 9981da177e4SLinus Torvalds pdev->subsystem_device); 9991da177e4SLinus Torvalds 1000662a98fbSAmol Lad rc = pci_enable_device(pdev); 1001662a98fbSAmol Lad if (rc) { 1002be7bce25STaku Izumi ctrl_err(ctrl, "pci_enable_device failed\n"); 10030abe68ceSKenji Kaneshige goto abort; 1004662a98fbSAmol Lad } 10051da177e4SLinus Torvalds 10060455986cSKenji Kaneshige if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) { 1007be7bce25STaku Izumi ctrl_err(ctrl, "Cannot reserve MMIO region\n"); 1008662a98fbSAmol Lad rc = -1; 10090abe68ceSKenji Kaneshige goto abort; 10101da177e4SLinus Torvalds } 10111da177e4SLinus Torvalds 10120abe68ceSKenji Kaneshige ctrl->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size); 10130abe68ceSKenji Kaneshige if (!ctrl->creg) { 1014be7bce25STaku Izumi ctrl_err(ctrl, "Cannot remap MMIO region %lx @ %lx\n", 1015be7bce25STaku Izumi ctrl->mmio_size, ctrl->mmio_base); 10160455986cSKenji Kaneshige release_mem_region(ctrl->mmio_base, ctrl->mmio_size); 1017662a98fbSAmol Lad rc = -1; 10180abe68ceSKenji Kaneshige goto abort; 10191da177e4SLinus Torvalds } 1020be7bce25STaku Izumi ctrl_dbg(ctrl, "ctrl->creg %p\n", ctrl->creg); 10211da177e4SLinus Torvalds 10226aa4cdd0SIngo Molnar mutex_init(&ctrl->crit_sect); 1023d29aaddaSKenji Kaneshige mutex_init(&ctrl->cmd_lock); 1024d29aaddaSKenji Kaneshige 10251da177e4SLinus Torvalds /* Setup wait queue */ 10261da177e4SLinus Torvalds init_waitqueue_head(&ctrl->queue); 10271da177e4SLinus Torvalds 102875d97c59SKenji Kaneshige ctrl->hpc_ops = &shpchp_hpc_ops; 102975d97c59SKenji Kaneshige 10301da177e4SLinus Torvalds /* Return PCI Controller Info */ 103175d97c59SKenji Kaneshige slot_config = shpc_readl(ctrl, SLOT_CONFIG); 10320abe68ceSKenji Kaneshige ctrl->slot_device_offset = (slot_config & FIRST_DEV_NUM) >> 8; 10330abe68ceSKenji Kaneshige ctrl->num_slots = slot_config & SLOT_NUM; 10340abe68ceSKenji Kaneshige ctrl->first_slot = (slot_config & PSN) >> 16; 10350abe68ceSKenji Kaneshige ctrl->slot_num_inc = ((slot_config & UPDOWN) >> 29) ? 1 : -1; 10361da177e4SLinus Torvalds 10371da177e4SLinus Torvalds /* Mask Global Interrupt Mask & Command Complete Interrupt Mask */ 103875d97c59SKenji Kaneshige tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); 1039be7bce25STaku Izumi ctrl_dbg(ctrl, "SERR_INTR_ENABLE = %x\n", tempdword); 1040e7138723SKenji Kaneshige tempdword |= (GLOBAL_INTR_MASK | GLOBAL_SERR_MASK | 1041e7138723SKenji Kaneshige COMMAND_INTR_MASK | ARBITER_SERR_MASK); 1042e7138723SKenji Kaneshige tempdword &= ~SERR_INTR_RSVDZ_MASK; 104375d97c59SKenji Kaneshige shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword); 104475d97c59SKenji Kaneshige tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); 1045be7bce25STaku Izumi ctrl_dbg(ctrl, "SERR_INTR_ENABLE = %x\n", tempdword); 10461da177e4SLinus Torvalds 10471da177e4SLinus Torvalds /* Mask the MRL sensor SERR Mask of individual slot in 10481da177e4SLinus Torvalds * Slot SERR-INT Mask & clear all the existing event if any 10491da177e4SLinus Torvalds */ 10500abe68ceSKenji Kaneshige for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { 10512b34da7eSKenji Kaneshige slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); 1052be7bce25STaku Izumi ctrl_dbg(ctrl, "Default Logical Slot Register %d value %x\n", 1053be7bce25STaku Izumi hp_slot, slot_reg); 1054795eb5c4SKenji Kaneshige slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK | 1055795eb5c4SKenji Kaneshige BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK | 1056795eb5c4SKenji Kaneshige CON_PFAULT_INTR_MASK | MRL_CHANGE_SERR_MASK | 1057795eb5c4SKenji Kaneshige CON_PFAULT_SERR_MASK); 1058795eb5c4SKenji Kaneshige slot_reg &= ~SLOT_REG_RSVDZ_MASK; 1059795eb5c4SKenji Kaneshige shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); 10601da177e4SLinus Torvalds } 10611da177e4SLinus Torvalds 10620abe68ceSKenji Kaneshige if (shpchp_poll_mode) { 10630abe68ceSKenji Kaneshige /* Install interrupt polling timer. Start with 10 sec delay */ 10640abe68ceSKenji Kaneshige init_timer(&ctrl->poll_timer); 10650abe68ceSKenji Kaneshige start_int_poll_timer(ctrl, 10); 10661da177e4SLinus Torvalds } else { 10671da177e4SLinus Torvalds /* Installs the interrupt handler */ 10681da177e4SLinus Torvalds rc = pci_enable_msi(pdev); 10691da177e4SLinus Torvalds if (rc) { 1070f98ca311STaku Izumi ctrl_info(ctrl, 1071f98ca311STaku Izumi "Can't get msi for the hotplug controller\n"); 1072f98ca311STaku Izumi ctrl_info(ctrl, 1073f98ca311STaku Izumi "Use INTx for the hotplug controller\n"); 10740abe68ceSKenji Kaneshige } 10751da177e4SLinus Torvalds 10760abe68ceSKenji Kaneshige rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED, 10770abe68ceSKenji Kaneshige MY_NAME, (void *)ctrl); 1078be7bce25STaku Izumi ctrl_dbg(ctrl, "request_irq %d for hpc%d (returns %d)\n", 1079be7bce25STaku Izumi ctrl->pci_dev->irq, 10800abe68ceSKenji Kaneshige atomic_read(&shpchp_num_controllers), rc); 10811da177e4SLinus Torvalds if (rc) { 1082f98ca311STaku Izumi ctrl_err(ctrl, "Can't get irq %d for the hotplug " 1083f98ca311STaku Izumi "controller\n", ctrl->pci_dev->irq); 10840abe68ceSKenji Kaneshige goto abort_iounmap; 10851da177e4SLinus Torvalds } 10861da177e4SLinus Torvalds } 1087be7bce25STaku Izumi ctrl_dbg(ctrl, "HPC at %s irq=%x\n", pci_name(pdev), pdev->irq); 10881da177e4SLinus Torvalds 1089795eb5c4SKenji Kaneshige /* 109082d5f4aaSKenji Kaneshige * If this is the first controller to be initialized, 109182d5f4aaSKenji Kaneshige * initialize the shpchpd work queue 109282d5f4aaSKenji Kaneshige */ 109382d5f4aaSKenji Kaneshige if (atomic_add_return(1, &shpchp_num_controllers) == 1) { 109482d5f4aaSKenji Kaneshige shpchp_wq = create_singlethread_workqueue("shpchpd"); 1095662a98fbSAmol Lad if (!shpchp_wq) { 1096662a98fbSAmol Lad rc = -ENOMEM; 10970abe68ceSKenji Kaneshige goto abort_iounmap; 1098662a98fbSAmol Lad } 109982d5f4aaSKenji Kaneshige } 110082d5f4aaSKenji Kaneshige 110182d5f4aaSKenji Kaneshige /* 1102795eb5c4SKenji Kaneshige * Unmask all event interrupts of all slots 1103795eb5c4SKenji Kaneshige */ 11040abe68ceSKenji Kaneshige for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { 11052b34da7eSKenji Kaneshige slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); 1106be7bce25STaku Izumi ctrl_dbg(ctrl, "Default Logical Slot Register %d value %x\n", 1107be7bce25STaku Izumi hp_slot, slot_reg); 1108795eb5c4SKenji Kaneshige slot_reg &= ~(PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK | 1109795eb5c4SKenji Kaneshige BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK | 1110795eb5c4SKenji Kaneshige CON_PFAULT_INTR_MASK | SLOT_REG_RSVDZ_MASK); 1111795eb5c4SKenji Kaneshige shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); 11121da177e4SLinus Torvalds } 11131da177e4SLinus Torvalds if (!shpchp_poll_mode) { 11141da177e4SLinus Torvalds /* Unmask all general input interrupts and SERR */ 111575d97c59SKenji Kaneshige tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); 1116e7138723SKenji Kaneshige tempdword &= ~(GLOBAL_INTR_MASK | COMMAND_INTR_MASK | 1117e7138723SKenji Kaneshige SERR_INTR_RSVDZ_MASK); 111875d97c59SKenji Kaneshige shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword); 111975d97c59SKenji Kaneshige tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); 1120be7bce25STaku Izumi ctrl_dbg(ctrl, "SERR_INTR_ENABLE = %x\n", tempdword); 11211da177e4SLinus Torvalds } 11221da177e4SLinus Torvalds 11231da177e4SLinus Torvalds return 0; 11241da177e4SLinus Torvalds 11251da177e4SLinus Torvalds /* We end up here for the many possible ways to fail this API. */ 11260abe68ceSKenji Kaneshige abort_iounmap: 11270abe68ceSKenji Kaneshige iounmap(ctrl->creg); 11281da177e4SLinus Torvalds abort: 1129662a98fbSAmol Lad return rc; 11301da177e4SLinus Torvalds } 1131