11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Standard PCI Hot Plug Driver 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1995,2001 Compaq Computer Corporation 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001 IBM Corp. 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2003-2004 Intel Corporation 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All rights reserved. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or (at 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * your option) any later version. 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, but 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * WITHOUT ANY WARRANTY; without even the implied warranty of 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NON INFRINGEMENT. See the GNU General Public License for more 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * details. 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 268cf4c19523b7694c88bba716d88fb659fa702411Kristen Accardi * Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 34d4d28dd4b12649d02a89d19e6bd12ab92a6fcd4eAndrew Morton#include <linux/interrupt.h> 35d4d28dd4b12649d02a89d19e6bd12ab92a6fcd4eAndrew Morton 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "shpchp.h" 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Slot Available Register I field definition */ 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SLOT_33MHZ 0x0000001f 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SLOT_66MHZ_PCIX 0x00001f00 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SLOT_100MHZ_PCIX 0x001f0000 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SLOT_133MHZ_PCIX 0x1f000000 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Slot Available Register II field definition */ 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SLOT_66MHZ 0x0000001f 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SLOT_66MHZ_PCIX_266 0x00000f00 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SLOT_100MHZ_PCIX_266 0x0000f000 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SLOT_133MHZ_PCIX_266 0x000f0000 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SLOT_66MHZ_PCIX_533 0x00f00000 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SLOT_100MHZ_PCIX_533 0x0f000000 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SLOT_133MHZ_PCIX_533 0xf0000000 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Slot Configuration */ 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SLOT_NUM 0x0000001F 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FIRST_DEV_NUM 0x00001F00 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PSN 0x07FF0000 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define UPDOWN 0x20000000 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MRLSENSOR 0x40000000 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ATTN_BUTTON 0x80000000 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 612b34da7e61383b4b7773d2d4e776e58725794347Kenji Kaneshige/* 62c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige * Interrupt Locator Register definitions 63c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige */ 64c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige#define CMD_INTR_PENDING (1 << 0) 65c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige#define SLOT_INTR_PENDING(i) (1 << (i + 1)) 66c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige 67c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige/* 68e7138723692e43b7d43578746ad21bf194847527Kenji Kaneshige * Controller SERR-INT Register 69e7138723692e43b7d43578746ad21bf194847527Kenji Kaneshige */ 70e7138723692e43b7d43578746ad21bf194847527Kenji Kaneshige#define GLOBAL_INTR_MASK (1 << 0) 71e7138723692e43b7d43578746ad21bf194847527Kenji Kaneshige#define GLOBAL_SERR_MASK (1 << 1) 72e7138723692e43b7d43578746ad21bf194847527Kenji Kaneshige#define COMMAND_INTR_MASK (1 << 2) 73e7138723692e43b7d43578746ad21bf194847527Kenji Kaneshige#define ARBITER_SERR_MASK (1 << 3) 74e7138723692e43b7d43578746ad21bf194847527Kenji Kaneshige#define COMMAND_DETECTED (1 << 16) 75e7138723692e43b7d43578746ad21bf194847527Kenji Kaneshige#define ARBITER_DETECTED (1 << 17) 76e7138723692e43b7d43578746ad21bf194847527Kenji Kaneshige#define SERR_INTR_RSVDZ_MASK 0xfffc0000 77e7138723692e43b7d43578746ad21bf194847527Kenji Kaneshige 78e7138723692e43b7d43578746ad21bf194847527Kenji Kaneshige/* 792b34da7e61383b4b7773d2d4e776e58725794347Kenji Kaneshige * Logical Slot Register definitions 802b34da7e61383b4b7773d2d4e776e58725794347Kenji Kaneshige */ 812b34da7e61383b4b7773d2d4e776e58725794347Kenji Kaneshige#define SLOT_REG(i) (SLOT1 + (4 * i)) 822b34da7e61383b4b7773d2d4e776e58725794347Kenji Kaneshige 835858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define SLOT_STATE_SHIFT (0) 845858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define SLOT_STATE_MASK (3 << 0) 855858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define SLOT_STATE_PWRONLY (1) 865858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define SLOT_STATE_ENABLED (2) 875858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define SLOT_STATE_DISABLED (3) 885858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define PWR_LED_STATE_SHIFT (2) 895858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define PWR_LED_STATE_MASK (3 << 2) 905858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define ATN_LED_STATE_SHIFT (4) 915858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define ATN_LED_STATE_MASK (3 << 4) 925858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define ATN_LED_STATE_ON (1) 935858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define ATN_LED_STATE_BLINK (2) 945858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define ATN_LED_STATE_OFF (3) 955858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define POWER_FAULT (1 << 6) 965858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define ATN_BUTTON (1 << 7) 975858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define MRL_SENSOR (1 << 8) 985858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define MHZ66_CAP (1 << 9) 995858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define PRSNT_SHIFT (10) 1005858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define PRSNT_MASK (3 << 10) 1015858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define PCIX_CAP_SHIFT (12) 1025858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define PCIX_CAP_MASK_PI1 (3 << 12) 1035858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define PCIX_CAP_MASK_PI2 (7 << 12) 1045858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define PRSNT_CHANGE_DETECTED (1 << 16) 1055858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define ISO_PFAULT_DETECTED (1 << 17) 1065858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define BUTTON_PRESS_DETECTED (1 << 18) 1075858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define MRL_CHANGE_DETECTED (1 << 19) 1085858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define CON_PFAULT_DETECTED (1 << 20) 1095858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define PRSNT_CHANGE_INTR_MASK (1 << 24) 1105858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define ISO_PFAULT_INTR_MASK (1 << 25) 1115858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define BUTTON_PRESS_INTR_MASK (1 << 26) 1125858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define MRL_CHANGE_INTR_MASK (1 << 27) 1135858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define CON_PFAULT_INTR_MASK (1 << 28) 1145858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define MRL_CHANGE_SERR_MASK (1 << 29) 1155858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige#define CON_PFAULT_SERR_MASK (1 << 30) 1163b8fdb759e6ed446433c6dfd5a226d9007925596Dan Carpenter#define SLOT_REG_RSVDZ_MASK ((1 << 15) | (7 << 21)) 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1184085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige/* 1194085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige * SHPC Command Code definitnions 1204085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige * 1214085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige * Slot Operation 00h - 3Fh 1224085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige * Set Bus Segment Speed/Mode A 40h - 47h 1234085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige * Power-Only All Slots 48h 1244085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige * Enable All Slots 49h 1254085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige * Set Bus Segment Speed/Mode B (PI=2) 50h - 5Fh 1264085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige * Reserved Command Codes 60h - BFh 1274085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige * Vendor Specific Commands C0h - FFh 1284085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige */ 1294085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige#define SET_SLOT_PWR 0x01 /* Slot Operation */ 1304085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige#define SET_SLOT_ENABLE 0x02 1314085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige#define SET_SLOT_DISABLE 0x03 1324085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige#define SET_PWR_ON 0x04 1334085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige#define SET_PWR_BLINK 0x08 1344085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige#define SET_PWR_OFF 0x0c 1354085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige#define SET_ATTN_ON 0x10 1364085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige#define SET_ATTN_BLINK 0x20 1374085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige#define SET_ATTN_OFF 0x30 1384085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige#define SETA_PCI_33MHZ 0x40 /* Set Bus Segment Speed/Mode A */ 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SETA_PCI_66MHZ 0x41 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SETA_PCIX_66MHZ 0x42 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SETA_PCIX_100MHZ 0x43 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SETA_PCIX_133MHZ 0x44 1434085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige#define SETA_RESERVED1 0x45 1444085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige#define SETA_RESERVED2 0x46 1454085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige#define SETA_RESERVED3 0x47 1464085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige#define SET_PWR_ONLY_ALL 0x48 /* Power-Only All Slots */ 1474085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige#define SET_ENABLE_ALL 0x49 /* Enable All Slots */ 1484085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige#define SETB_PCI_33MHZ 0x50 /* Set Bus Segment Speed/Mode B */ 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SETB_PCI_66MHZ 0x51 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SETB_PCIX_66MHZ_PM 0x52 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SETB_PCIX_100MHZ_PM 0x53 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SETB_PCIX_133MHZ_PM 0x54 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SETB_PCIX_66MHZ_EM 0x55 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SETB_PCIX_100MHZ_EM 0x56 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SETB_PCIX_133MHZ_EM 0x57 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SETB_PCIX_66MHZ_266 0x58 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SETB_PCIX_100MHZ_266 0x59 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SETB_PCIX_133MHZ_266 0x5a 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SETB_PCIX_66MHZ_533 0x5b 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SETB_PCIX_100MHZ_533 0x5c 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SETB_PCIX_133MHZ_533 0x5d 1624085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige#define SETB_RESERVED1 0x5e 1634085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige#define SETB_RESERVED2 0x5f 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1654085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige/* 1664085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige * SHPC controller command error code 1674085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige */ 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SWITCH_OPEN 0x1 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INVALID_CMD 0x2 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INVALID_SPEED_MODE 0x4 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1724085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige/* 1734085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige * For accessing SHPC Working Register Set via PCI Configuration Space 1744085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige */ 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DWORD_SELECT 0x2 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DWORD_DATA 0x4 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Field Offset in Logical Slot Register - byte boundary */ 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SLOT_EVENT_LATCH 0x2 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SLOT_SERR_INT_MASK 0x3 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1827d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t shpc_isr(int irq, void *dev_id); 1830abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshigestatic void start_int_poll_timer(struct controller *ctrl, int sec); 184d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccfKenji Kaneshigestatic int hpc_check_cmd_status(struct controller *ctrl); 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18675d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshigestatic inline u8 shpc_readb(struct controller *ctrl, int reg) 18775d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige{ 1880abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige return readb(ctrl->creg + reg); 18975d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige} 19075d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige 19175d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshigestatic inline void shpc_writeb(struct controller *ctrl, int reg, u8 val) 19275d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige{ 1930abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige writeb(val, ctrl->creg + reg); 19475d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige} 19575d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige 19675d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshigestatic inline u16 shpc_readw(struct controller *ctrl, int reg) 19775d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige{ 1980abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige return readw(ctrl->creg + reg); 19975d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige} 20075d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige 20175d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshigestatic inline void shpc_writew(struct controller *ctrl, int reg, u16 val) 20275d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige{ 2030abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige writew(val, ctrl->creg + reg); 20475d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige} 20575d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige 20675d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshigestatic inline u32 shpc_readl(struct controller *ctrl, int reg) 20775d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige{ 2080abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige return readl(ctrl->creg + reg); 20975d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige} 21075d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige 21175d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshigestatic inline void shpc_writel(struct controller *ctrl, int reg, u32 val) 21275d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige{ 2130abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige writel(val, ctrl->creg + reg); 21475d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige} 21575d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige 21675d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshigestatic inline int shpc_indirect_read(struct controller *ctrl, int index, 21775d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige u32 *value) 21875d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige{ 21975d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige int rc; 22075d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige u32 cap_offset = ctrl->cap_offset; 22175d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige struct pci_dev *pdev = ctrl->pci_dev; 22275d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige 22375d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige rc = pci_write_config_byte(pdev, cap_offset + DWORD_SELECT, index); 22475d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige if (rc) 22575d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige return rc; 22675d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value); 22775d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige} 22875d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige 229f42639572680f4d69d9522f91c65e793ebeca098Kenji Kaneshige/* 230f42639572680f4d69d9522f91c65e793ebeca098Kenji Kaneshige * This is the interrupt polling timeout function. 231f42639572680f4d69d9522f91c65e793ebeca098Kenji Kaneshige */ 2320abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshigestatic void int_poll_timeout(unsigned long data) 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2340abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige struct controller *ctrl = (struct controller *)data; 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 236f42639572680f4d69d9522f91c65e793ebeca098Kenji Kaneshige /* Poll for interrupt events. regs == NULL => polling */ 2370abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige shpc_isr(0, ctrl); 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2390abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige init_timer(&ctrl->poll_timer); 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!shpchp_poll_time) 241f42639572680f4d69d9522f91c65e793ebeca098Kenji Kaneshige shpchp_poll_time = 2; /* default polling interval is 2 sec */ 242f42639572680f4d69d9522f91c65e793ebeca098Kenji Kaneshige 2430abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige start_int_poll_timer(ctrl, shpchp_poll_time); 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 246f42639572680f4d69d9522f91c65e793ebeca098Kenji Kaneshige/* 247f42639572680f4d69d9522f91c65e793ebeca098Kenji Kaneshige * This function starts the interrupt polling timer. 248f42639572680f4d69d9522f91c65e793ebeca098Kenji Kaneshige */ 2490abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshigestatic void start_int_poll_timer(struct controller *ctrl, int sec) 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 251f42639572680f4d69d9522f91c65e793ebeca098Kenji Kaneshige /* Clamp to sane value */ 252f42639572680f4d69d9522f91c65e793ebeca098Kenji Kaneshige if ((sec <= 0) || (sec > 60)) 253f42639572680f4d69d9522f91c65e793ebeca098Kenji Kaneshige sec = 2; 254f42639572680f4d69d9522f91c65e793ebeca098Kenji Kaneshige 2550abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige ctrl->poll_timer.function = &int_poll_timeout; 2560abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige ctrl->poll_timer.data = (unsigned long)ctrl; 2570abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige ctrl->poll_timer.expires = jiffies + sec * HZ; 2580abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige add_timer(&ctrl->poll_timer); 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261d1729ccecd7ba9ceb6dca1c973dbfd87041d0637Kenji Kaneshigestatic inline int is_ctrl_busy(struct controller *ctrl) 262d1729ccecd7ba9ceb6dca1c973dbfd87041d0637Kenji Kaneshige{ 263d1729ccecd7ba9ceb6dca1c973dbfd87041d0637Kenji Kaneshige u16 cmd_status = shpc_readw(ctrl, CMD_STATUS); 264d1729ccecd7ba9ceb6dca1c973dbfd87041d0637Kenji Kaneshige return cmd_status & 0x1; 265d1729ccecd7ba9ceb6dca1c973dbfd87041d0637Kenji Kaneshige} 266d1729ccecd7ba9ceb6dca1c973dbfd87041d0637Kenji Kaneshige 267b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige/* 268b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige * Returns 1 if SHPC finishes executing a command within 1 sec, 269b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige * otherwise returns 0. 270b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige */ 271b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshigestatic inline int shpc_poll_ctrl_busy(struct controller *ctrl) 272b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige{ 273b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige int i; 274b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige 275d1729ccecd7ba9ceb6dca1c973dbfd87041d0637Kenji Kaneshige if (!is_ctrl_busy(ctrl)) 276b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige return 1; 277b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige 278b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige /* Check every 0.1 sec for a total of 1 sec */ 279b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige for (i = 0; i < 10; i++) { 280b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige msleep(100); 281d1729ccecd7ba9ceb6dca1c973dbfd87041d0637Kenji Kaneshige if (!is_ctrl_busy(ctrl)) 282b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige return 1; 283b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige } 284b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige 285b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige return 0; 286b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige} 287b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige 288bd62e271401c5ebf33a0dd24d89baf706f213251Kenji Kaneshigestatic inline int shpc_wait_cmd(struct controller *ctrl) 289bd62e271401c5ebf33a0dd24d89baf706f213251Kenji Kaneshige{ 290bd62e271401c5ebf33a0dd24d89baf706f213251Kenji Kaneshige int retval = 0; 291b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige unsigned long timeout = msecs_to_jiffies(1000); 292b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige int rc; 293b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige 294b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige if (shpchp_poll_mode) 295b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige rc = shpc_poll_ctrl_busy(ctrl); 296b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige else 297b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige rc = wait_event_interruptible_timeout(ctrl->queue, 2986aa562c248e05db993e4a5f405f899c0cfabb7f2Kenji Kaneshige !is_ctrl_busy(ctrl), timeout); 299d1729ccecd7ba9ceb6dca1c973dbfd87041d0637Kenji Kaneshige if (!rc && is_ctrl_busy(ctrl)) { 300bd62e271401c5ebf33a0dd24d89baf706f213251Kenji Kaneshige retval = -EIO; 301f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_err(ctrl, "Command not completed in 1000 msec\n"); 302bd62e271401c5ebf33a0dd24d89baf706f213251Kenji Kaneshige } else if (rc < 0) { 303bd62e271401c5ebf33a0dd24d89baf706f213251Kenji Kaneshige retval = -EINTR; 304f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "Command was interrupted by a signal\n"); 305bd62e271401c5ebf33a0dd24d89baf706f213251Kenji Kaneshige } 306bd62e271401c5ebf33a0dd24d89baf706f213251Kenji Kaneshige 307bd62e271401c5ebf33a0dd24d89baf706f213251Kenji Kaneshige return retval; 308bd62e271401c5ebf33a0dd24d89baf706f213251Kenji Kaneshige} 309bd62e271401c5ebf33a0dd24d89baf706f213251Kenji Kaneshige 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 31275d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige struct controller *ctrl = slot->ctrl; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 cmd_status; 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 temp_word; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 317d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccfKenji Kaneshige mutex_lock(&slot->ctrl->cmd_lock); 318d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccfKenji Kaneshige 319b4a1efffcf8070dbc7734f27da10ce49fb9f2a34Kenji Kaneshige if (!shpc_poll_ctrl_busy(ctrl)) { 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* After 1 sec and and the controller is still busy */ 321be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "Controller is still busy after 1 sec\n"); 322d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccfKenji Kaneshige retval = -EBUSY; 323d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccfKenji Kaneshige goto out; 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ++t_slot; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp_word = (t_slot << 8) | (cmd & 0xFF); 328f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_dbg(ctrl, "%s: t_slot %x cmd %x\n", __func__, t_slot, cmd); 3299f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* To make sure the Controller Busy bit is 0 before we send out the 3319f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige * command. 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 33375d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige shpc_writew(ctrl, CMD, temp_word); 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 335bd62e271401c5ebf33a0dd24d89baf706f213251Kenji Kaneshige /* 336bd62e271401c5ebf33a0dd24d89baf706f213251Kenji Kaneshige * Wait for command completion. 337bd62e271401c5ebf33a0dd24d89baf706f213251Kenji Kaneshige */ 338bd62e271401c5ebf33a0dd24d89baf706f213251Kenji Kaneshige retval = shpc_wait_cmd(slot->ctrl); 339d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccfKenji Kaneshige if (retval) 340d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccfKenji Kaneshige goto out; 341d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccfKenji Kaneshige 342d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccfKenji Kaneshige cmd_status = hpc_check_cmd_status(slot->ctrl); 343d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccfKenji Kaneshige if (cmd_status) { 344be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, 345be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi "Failed to issued command 0x%x (error code = %d)\n", 346be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi cmd, cmd_status); 347d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccfKenji Kaneshige retval = -EIO; 348d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccfKenji Kaneshige } 349d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccfKenji Kaneshige out: 350d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccfKenji Kaneshige mutex_unlock(&slot->ctrl->cmd_lock); 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int hpc_check_cmd_status(struct controller *ctrl) 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 3571555b33da0b27f933fbe08679935ce9d83c0e9e9Kenji Kaneshige u16 cmd_status = shpc_readw(ctrl, CMD_STATUS) & 0x000F; 3589f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd_status >> 1) { 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = SWITCH_OPEN; 365be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "Switch opened!\n"); 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = INVALID_CMD; 369be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "Invalid HPC command!\n"); 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 4: 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = INVALID_SPEED_MODE; 373be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "Invalid bus speed/mode!\n"); 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = cmd_status; 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int hpc_get_attention_status(struct slot *slot, u8 *status) 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 38575d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige struct controller *ctrl = slot->ctrl; 3861555b33da0b27f933fbe08679935ce9d83c0e9e9Kenji Kaneshige u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); 3871555b33da0b27f933fbe08679935ce9d83c0e9e9Kenji Kaneshige u8 state = (slot_reg & ATN_LED_STATE_MASK) >> ATN_LED_STATE_SHIFT; 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3895858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige switch (state) { 3905858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige case ATN_LED_STATE_ON: 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *status = 1; /* On */ 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3935858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige case ATN_LED_STATE_BLINK: 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *status = 2; /* Blink */ 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3965858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige case ATN_LED_STATE_OFF: 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *status = 0; /* Off */ 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4005858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige *status = 0xFF; /* Reserved */ 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int hpc_get_power_status(struct slot * slot, u8 *status) 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 40975d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige struct controller *ctrl = slot->ctrl; 4101555b33da0b27f933fbe08679935ce9d83c0e9e9Kenji Kaneshige u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); 4111555b33da0b27f933fbe08679935ce9d83c0e9e9Kenji Kaneshige u8 state = (slot_reg & SLOT_STATE_MASK) >> SLOT_STATE_SHIFT; 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4135858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige switch (state) { 4145858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige case SLOT_STATE_PWRONLY: 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *status = 2; /* Powered only */ 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4175858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige case SLOT_STATE_ENABLED: 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *status = 1; /* Enabled */ 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4205858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige case SLOT_STATE_DISABLED: 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *status = 0; /* Disabled */ 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4245858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige *status = 0xFF; /* Reserved */ 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4285858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige return 0; 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int hpc_get_latch_status(struct slot *slot, u8 *status) 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 43475d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige struct controller *ctrl = slot->ctrl; 4351555b33da0b27f933fbe08679935ce9d83c0e9e9Kenji Kaneshige u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4375858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige *status = !!(slot_reg & MRL_SENSOR); /* 0 -> close; 1 -> open */ 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int hpc_get_adapter_status(struct slot *slot, u8 *status) 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 44475d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige struct controller *ctrl = slot->ctrl; 4451555b33da0b27f933fbe08679935ce9d83c0e9e9Kenji Kaneshige u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); 4461555b33da0b27f933fbe08679935ce9d83c0e9e9Kenji Kaneshige u8 state = (slot_reg & PRSNT_MASK) >> PRSNT_SHIFT; 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4485858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige *status = (state != 0x3) ? 1 : 0; 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int hpc_get_prog_int(struct slot *slot, u8 *prog_int) 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 45575d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige struct controller *ctrl = slot->ctrl; 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45775d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige *prog_int = shpc_readb(ctrl, PROG_INTERFACE); 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 46575d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige struct controller *ctrl = slot->ctrl; 4662b34da7e61383b4b7773d2d4e776e58725794347Kenji Kaneshige u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); 4675858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige u8 m66_cap = !!(slot_reg & MHZ66_CAP); 468795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige u8 pi, pcix_cap; 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 470795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige if ((retval = hpc_get_prog_int(slot, &pi))) 471795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige return retval; 472795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige 473795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige switch (pi) { 474795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige case 1: 475795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige pcix_cap = (slot_reg & PCIX_CAP_MASK_PI1) >> PCIX_CAP_SHIFT; 476795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige break; 477795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige case 2: 478795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige pcix_cap = (slot_reg & PCIX_CAP_MASK_PI2) >> PCIX_CAP_SHIFT; 479795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige break; 480795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige default: 481795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige return -ENODEV; 482795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige } 483795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige 484f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_dbg(ctrl, "%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n", 485f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi __func__, slot_reg, pcix_cap, m66_cap); 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4870afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige switch (pcix_cap) { 4880afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige case 0x0: 4890afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige *value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; 4900afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige break; 4910afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige case 0x1: 4920afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige *value = PCI_SPEED_66MHz_PCIX; 4930afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige break; 4940afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige case 0x3: 4950afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige *value = PCI_SPEED_133MHz_PCIX; 4960afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige break; 4970afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige case 0x4: 4980afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige *value = PCI_SPEED_133MHz_PCIX_266; 4990afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige break; 5000afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige case 0x5: 5010afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige *value = PCI_SPEED_133MHz_PCIX_533; 5020afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige break; 5030afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige case 0x2: 5040afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige default: 5050afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige *value = PCI_SPEED_UNKNOWN; 5060afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige retval = -ENODEV; 5070afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige break; 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 510f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_dbg(ctrl, "Adapter speed = %d\n", *value); 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode) 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = 0; 5171555b33da0b27f933fbe08679935ce9d83c0e9e9Kenji Kaneshige struct controller *ctrl = slot->ctrl; 5181555b33da0b27f933fbe08679935ce9d83c0e9e9Kenji Kaneshige u16 sec_bus_status = shpc_readw(ctrl, SEC_BUS_CONFIG); 5191555b33da0b27f933fbe08679935ce9d83c0e9e9Kenji Kaneshige u8 pi = shpc_readb(ctrl, PROG_INTERFACE); 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pi == 2) { 52287d6c5593111844f308af7d5106b3fd259b36514Kenji Kaneshige *mode = (sec_bus_status & 0x0100) >> 8; 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -1; 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 527f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_dbg(ctrl, "Mode 1 ECC cap = %d\n", *mode); 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int hpc_query_power_fault(struct slot * slot) 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 53375d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige struct controller *ctrl = slot->ctrl; 5341555b33da0b27f933fbe08679935ce9d83c0e9e9Kenji Kaneshige u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Note: Logic 0 => fault */ 5375858759c2098c6792af1afa6d5ded94044740f9cKenji Kaneshige return !(slot_reg & POWER_FAULT); 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int hpc_set_attention_status(struct slot *slot, u8 value) 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 slot_cmd = 0; 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (value) { 5459f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige case 0 : 5464085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige slot_cmd = SET_ATTN_OFF; /* OFF */ 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: 5494085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige slot_cmd = SET_ATTN_ON; /* ON */ 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: 5524085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige slot_cmd = SET_ATTN_BLINK; /* BLINK */ 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 558d4fbf600666569c3921d12bdcfcfdb2cdb4fd5fbKenji Kaneshige return shpc_write_cmd(slot, slot->hp_slot, slot_cmd); 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void hpc_set_green_led_on(struct slot *slot) 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5644085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige shpc_write_cmd(slot, slot->hp_slot, SET_PWR_ON); 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void hpc_set_green_led_off(struct slot *slot) 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5694085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige shpc_write_cmd(slot, slot->hp_slot, SET_PWR_OFF); 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void hpc_set_green_led_blink(struct slot *slot) 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5744085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige shpc_write_cmd(slot, slot->hp_slot, SET_PWR_BLINK); 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void hpc_release_ctlr(struct controller *ctrl) 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 579f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige int i; 580d49f2c49c39bbd0cb2069fe11c1630c709061037Kenji Kaneshige u32 slot_reg, serr_int; 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 582f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige /* 583795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige * Mask event interrupts and SERRs of all slots 584f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige */ 585795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige for (i = 0; i < ctrl->num_slots; i++) { 586795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige slot_reg = shpc_readl(ctrl, SLOT_REG(i)); 587795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK | 588795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK | 589795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige CON_PFAULT_INTR_MASK | MRL_CHANGE_SERR_MASK | 590795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige CON_PFAULT_SERR_MASK); 591795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige slot_reg &= ~SLOT_REG_RSVDZ_MASK; 592795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige shpc_writel(ctrl, SLOT_REG(i), slot_reg); 593795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige } 594f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige 595f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige cleanup_slots(ctrl); 596f7391f5325ea744f0632f7ef39a90085162743acKenji Kaneshige 597d49f2c49c39bbd0cb2069fe11c1630c709061037Kenji Kaneshige /* 5983609801ecc63e7def325752a19065980410d37adJoe Perches * Mask SERR and System Interrupt generation 599d49f2c49c39bbd0cb2069fe11c1630c709061037Kenji Kaneshige */ 600d49f2c49c39bbd0cb2069fe11c1630c709061037Kenji Kaneshige serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE); 601d49f2c49c39bbd0cb2069fe11c1630c709061037Kenji Kaneshige serr_int |= (GLOBAL_INTR_MASK | GLOBAL_SERR_MASK | 602d49f2c49c39bbd0cb2069fe11c1630c709061037Kenji Kaneshige COMMAND_INTR_MASK | ARBITER_SERR_MASK); 603d49f2c49c39bbd0cb2069fe11c1630c709061037Kenji Kaneshige serr_int &= ~SERR_INTR_RSVDZ_MASK; 604d49f2c49c39bbd0cb2069fe11c1630c709061037Kenji Kaneshige shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); 605d49f2c49c39bbd0cb2069fe11c1630c709061037Kenji Kaneshige 6060abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige if (shpchp_poll_mode) 6070abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige del_timer(&ctrl->poll_timer); 6080abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige else { 6090abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige free_irq(ctrl->pci_dev->irq, ctrl); 6100abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige pci_disable_msi(ctrl->pci_dev); 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6130abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige iounmap(ctrl->creg); 6140abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige release_mem_region(ctrl->mmio_base, ctrl->mmio_size); 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int hpc_power_on_slot(struct slot * slot) 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 619d4fbf600666569c3921d12bdcfcfdb2cdb4fd5fbKenji Kaneshige int retval; 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6214085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_PWR); 6221555b33da0b27f933fbe08679935ce9d83c0e9e9Kenji Kaneshige if (retval) 623f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_err(slot->ctrl, "%s: Write command failed!\n", __func__); 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6251555b33da0b27f933fbe08679935ce9d83c0e9e9Kenji Kaneshige return retval; 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int hpc_slot_enable(struct slot * slot) 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 630d4fbf600666569c3921d12bdcfcfdb2cdb4fd5fbKenji Kaneshige int retval; 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6324085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige /* Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */ 6334085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige retval = shpc_write_cmd(slot, slot->hp_slot, 6344085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige SET_SLOT_ENABLE | SET_PWR_BLINK | SET_ATTN_OFF); 6351555b33da0b27f933fbe08679935ce9d83c0e9e9Kenji Kaneshige if (retval) 636f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_err(slot->ctrl, "%s: Write command failed!\n", __func__); 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6381555b33da0b27f933fbe08679935ce9d83c0e9e9Kenji Kaneshige return retval; 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int hpc_slot_disable(struct slot * slot) 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 643d4fbf600666569c3921d12bdcfcfdb2cdb4fd5fbKenji Kaneshige int retval; 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6454085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige /* Slot - Disable, Power Indicator - Off, Attention Indicator - On */ 6464085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige retval = shpc_write_cmd(slot, slot->hp_slot, 6474085399da3c2176ba8ed64e93a2722907d41df3fKenji Kaneshige SET_SLOT_DISABLE | SET_PWR_OFF | SET_ATTN_ON); 6481555b33da0b27f933fbe08679935ce9d83c0e9e9Kenji Kaneshige if (retval) 649f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_err(slot->ctrl, "%s: Write command failed!\n", __func__); 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6511555b33da0b27f933fbe08679935ce9d83c0e9e9Kenji Kaneshige return retval; 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6543749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcoxstatic int shpc_get_cur_bus_speed(struct controller *ctrl) 6553749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox{ 6563749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox int retval = 0; 6573749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox struct pci_bus *bus = ctrl->pci_dev->subordinate; 6583749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; 6593749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox u16 sec_bus_reg = shpc_readw(ctrl, SEC_BUS_CONFIG); 6603749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox u8 pi = shpc_readb(ctrl, PROG_INTERFACE); 6613749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7); 6623749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox 6633749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox if ((pi == 1) && (speed_mode > 4)) { 6643749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox retval = -ENODEV; 6653749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox goto out; 6663749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox } 6673749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox 6683749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox switch (speed_mode) { 6693749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox case 0x0: 6703749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox bus_speed = PCI_SPEED_33MHz; 6713749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox break; 6723749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox case 0x1: 6733749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox bus_speed = PCI_SPEED_66MHz; 6743749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox break; 6753749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox case 0x2: 6763749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox bus_speed = PCI_SPEED_66MHz_PCIX; 6773749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox break; 6783749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox case 0x3: 6793749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox bus_speed = PCI_SPEED_100MHz_PCIX; 6803749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox break; 6813749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox case 0x4: 6823749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox bus_speed = PCI_SPEED_133MHz_PCIX; 6833749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox break; 6843749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox case 0x5: 6853749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox bus_speed = PCI_SPEED_66MHz_PCIX_ECC; 6863749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox break; 6873749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox case 0x6: 6883749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox bus_speed = PCI_SPEED_100MHz_PCIX_ECC; 6893749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox break; 6903749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox case 0x7: 6913749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox bus_speed = PCI_SPEED_133MHz_PCIX_ECC; 6923749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox break; 6933749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox case 0x8: 6943749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox bus_speed = PCI_SPEED_66MHz_PCIX_266; 6953749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox break; 6963749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox case 0x9: 6973749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox bus_speed = PCI_SPEED_100MHz_PCIX_266; 6983749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox break; 6993749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox case 0xa: 7003749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox bus_speed = PCI_SPEED_133MHz_PCIX_266; 7013749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox break; 7023749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox case 0xb: 7033749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox bus_speed = PCI_SPEED_66MHz_PCIX_533; 7043749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox break; 7053749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox case 0xc: 7063749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox bus_speed = PCI_SPEED_100MHz_PCIX_533; 7073749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox break; 7083749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox case 0xd: 7093749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox bus_speed = PCI_SPEED_133MHz_PCIX_533; 7103749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox break; 7113749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox default: 7123749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox retval = -ENODEV; 7133749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox break; 7143749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox } 7153749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox 7163749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox out: 7173749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox bus->cur_bus_speed = bus_speed; 7183749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox dbg("Current bus speed = %d\n", bus_speed); 7193749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox return retval; 7203749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox} 7213749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox 7223749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7250afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige int retval; 72675d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige struct controller *ctrl = slot->ctrl; 7270afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige u8 pi, cmd; 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 72975d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige pi = shpc_readb(ctrl, PROG_INTERFACE); 7300afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX)) 7310afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige return -EINVAL; 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7330afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige switch (value) { 7340afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige case PCI_SPEED_33MHz: 7350afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige cmd = SETA_PCI_33MHZ; 7360afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige break; 7370afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige case PCI_SPEED_66MHz: 7380afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige cmd = SETA_PCI_66MHZ; 7390afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige break; 7400afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige case PCI_SPEED_66MHz_PCIX: 7410afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige cmd = SETA_PCIX_66MHZ; 7420afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige break; 7430afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige case PCI_SPEED_100MHz_PCIX: 7440afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige cmd = SETA_PCIX_100MHZ; 7450afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige break; 7460afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige case PCI_SPEED_133MHz_PCIX: 7470afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige cmd = SETA_PCIX_133MHZ; 7480afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige break; 7490afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige case PCI_SPEED_66MHz_PCIX_ECC: 7500afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige cmd = SETB_PCIX_66MHZ_EM; 7510afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige break; 7520afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige case PCI_SPEED_100MHz_PCIX_ECC: 7530afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige cmd = SETB_PCIX_100MHZ_EM; 7540afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige break; 7550afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige case PCI_SPEED_133MHz_PCIX_ECC: 7560afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige cmd = SETB_PCIX_133MHZ_EM; 7570afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige break; 7580afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige case PCI_SPEED_66MHz_PCIX_266: 7590afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige cmd = SETB_PCIX_66MHZ_266; 7600afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige break; 7610afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige case PCI_SPEED_100MHz_PCIX_266: 7620afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige cmd = SETB_PCIX_100MHZ_266; 7630afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige break; 7640afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige case PCI_SPEED_133MHz_PCIX_266: 7650afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige cmd = SETB_PCIX_133MHZ_266; 7660afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige break; 7670afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige case PCI_SPEED_66MHz_PCIX_533: 7680afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige cmd = SETB_PCIX_66MHZ_533; 7690afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige break; 7700afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige case PCI_SPEED_100MHz_PCIX_533: 7710afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige cmd = SETB_PCIX_100MHZ_533; 7720afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige break; 7730afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige case PCI_SPEED_133MHz_PCIX_533: 7740afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige cmd = SETB_PCIX_133MHZ_533; 7750afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige break; 7760afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige default: 7770afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige return -EINVAL; 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7790afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige 7800afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige retval = shpc_write_cmd(slot, 0, cmd); 7810afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige if (retval) 782f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_err(ctrl, "%s: Write command failed!\n", __func__); 7833749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox else 7843749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox shpc_get_cur_bus_speed(ctrl); 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7897d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t shpc_isr(int irq, void *dev_id) 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 791c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige struct controller *ctrl = (struct controller *)dev_id; 792c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige u32 serr_int, slot_reg, intr_loc, intr_loc2; 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int hp_slot; 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check to see if it was our interrupt */ 79675d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige intr_loc = shpc_readl(ctrl, INTR_LOC); 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!intr_loc) 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_NONE; 799c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige 800f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_dbg(ctrl, "%s: intr_loc = %x\n", __func__, intr_loc); 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!shpchp_poll_mode) { 803c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige /* 804c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige * Mask Global Interrupt Mask - see implementation 805c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige * note on p. 139 of SHPC spec rev 1.0 806c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige */ 807c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE); 808c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige serr_int |= GLOBAL_INTR_MASK; 809c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige serr_int &= ~SERR_INTR_RSVDZ_MASK; 810c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 81275d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige intr_loc2 = shpc_readl(ctrl, INTR_LOC); 813f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_dbg(ctrl, "%s: intr_loc2 = %x\n", __func__, intr_loc2); 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 816c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige if (intr_loc & CMD_INTR_PENDING) { 8179f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige /* 8189f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige * Command Complete Interrupt Pending 819f467f6187fc60c954a9509b3a3e17ef89a4f6f22Kenji Kaneshige * RO only - clear by writing 1 to the Command Completion 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Detect bit in Controller SERR-INT register 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 822c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE); 823c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige serr_int &= ~SERR_INTR_RSVDZ_MASK; 824c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); 825c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wake_up_interruptible(&ctrl->queue); 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 829c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige if (!(intr_loc & ~CMD_INTR_PENDING)) 830e4e73041ecc4a3559c42ed9489f58531c2a8646bKenji Kaneshige goto out; 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8329f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { 833c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige /* To find out which slot has interrupt pending */ 834c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige if (!(intr_loc & SLOT_INTR_PENDING(hp_slot))) 835c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige continue; 836c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige 837c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); 838be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, "Slot %x with intr, slot register = %x\n", 839be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi hp_slot, slot_reg); 840c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige 841c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige if (slot_reg & MRL_CHANGE_DETECTED) 8420abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige shpchp_handle_switch_change(hp_slot, ctrl); 843c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige 844c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige if (slot_reg & BUTTON_PRESS_DETECTED) 8450abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige shpchp_handle_attention_button(hp_slot, ctrl); 846c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige 847c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige if (slot_reg & PRSNT_CHANGE_DETECTED) 8480abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige shpchp_handle_presence_change(hp_slot, ctrl); 849c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige 850c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige if (slot_reg & (ISO_PFAULT_DETECTED | CON_PFAULT_DETECTED)) 8510abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige shpchp_handle_power_fault(hp_slot, ctrl); 852c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige 853c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige /* Clear all slot events */ 854c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige slot_reg &= ~SLOT_REG_RSVDZ_MASK; 855c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 857e4e73041ecc4a3559c42ed9489f58531c2a8646bKenji Kaneshige out: 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!shpchp_poll_mode) { 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Unmask Global Interrupt Mask */ 860c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE); 861c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige serr_int &= ~(GLOBAL_INTR_MASK | SERR_INTR_RSVDZ_MASK); 862c4cecc1937cafd8505151452a9f7eea876a5bd9cKenji Kaneshige shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8649f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_HANDLED; 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8683749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcoxstatic int shpc_get_max_bus_speed(struct controller *ctrl) 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8700afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige int retval = 0; 8713749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox struct pci_bus *bus = ctrl->pci_dev->subordinate; 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; 87375d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige u8 pi = shpc_readb(ctrl, PROG_INTERFACE); 87475d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1); 87575d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige u32 slot_avail2 = shpc_readl(ctrl, SLOT_AVAIL2); 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pi == 2) { 8786558b6ab145ceead45632e4214cd5ef14f48f412Kenji Kaneshige if (slot_avail2 & SLOT_133MHZ_PCIX_533) 8790afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige bus_speed = PCI_SPEED_133MHz_PCIX_533; 8806558b6ab145ceead45632e4214cd5ef14f48f412Kenji Kaneshige else if (slot_avail2 & SLOT_100MHZ_PCIX_533) 8810afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige bus_speed = PCI_SPEED_100MHz_PCIX_533; 8826558b6ab145ceead45632e4214cd5ef14f48f412Kenji Kaneshige else if (slot_avail2 & SLOT_66MHZ_PCIX_533) 8830afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige bus_speed = PCI_SPEED_66MHz_PCIX_533; 8846558b6ab145ceead45632e4214cd5ef14f48f412Kenji Kaneshige else if (slot_avail2 & SLOT_133MHZ_PCIX_266) 8850afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige bus_speed = PCI_SPEED_133MHz_PCIX_266; 8866558b6ab145ceead45632e4214cd5ef14f48f412Kenji Kaneshige else if (slot_avail2 & SLOT_100MHZ_PCIX_266) 8870afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige bus_speed = PCI_SPEED_100MHz_PCIX_266; 8886558b6ab145ceead45632e4214cd5ef14f48f412Kenji Kaneshige else if (slot_avail2 & SLOT_66MHZ_PCIX_266) 8890afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige bus_speed = PCI_SPEED_66MHz_PCIX_266; 8900afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige } 8910afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige 8920afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige if (bus_speed == PCI_SPEED_UNKNOWN) { 8936558b6ab145ceead45632e4214cd5ef14f48f412Kenji Kaneshige if (slot_avail1 & SLOT_133MHZ_PCIX) 8940afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige bus_speed = PCI_SPEED_133MHz_PCIX; 8956558b6ab145ceead45632e4214cd5ef14f48f412Kenji Kaneshige else if (slot_avail1 & SLOT_100MHZ_PCIX) 8960afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige bus_speed = PCI_SPEED_100MHz_PCIX; 8976558b6ab145ceead45632e4214cd5ef14f48f412Kenji Kaneshige else if (slot_avail1 & SLOT_66MHZ_PCIX) 8980afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige bus_speed = PCI_SPEED_66MHz_PCIX; 8996558b6ab145ceead45632e4214cd5ef14f48f412Kenji Kaneshige else if (slot_avail2 & SLOT_66MHZ) 9000afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige bus_speed = PCI_SPEED_66MHz; 9016558b6ab145ceead45632e4214cd5ef14f48f412Kenji Kaneshige else if (slot_avail1 & SLOT_33MHZ) 9020afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige bus_speed = PCI_SPEED_33MHz; 9030afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige else 9040afabe906539b4e8b9e895f19ea31aabdf12f30bKenji Kaneshige retval = -ENODEV; 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9073749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox bus->max_bus_speed = bus_speed; 908f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_dbg(ctrl, "Max bus speed = %d\n", bus_speed); 9091555b33da0b27f933fbe08679935ce9d83c0e9e9Kenji Kaneshige 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct hpc_ops shpchp_hpc_ops = { 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .power_on_slot = hpc_power_on_slot, 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .slot_enable = hpc_slot_enable, 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .slot_disable = hpc_slot_disable, 9179f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige .set_bus_speed_mode = hpc_set_bus_speed_mode, 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set_attention_status = hpc_set_attention_status, 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_power_status = hpc_get_power_status, 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_attention_status = hpc_get_attention_status, 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_latch_status = hpc_get_latch_status, 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_adapter_status = hpc_get_adapter_status, 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_adapter_speed = hpc_get_adapter_speed, 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_mode1_ECC_cap = hpc_get_mode1_ECC_cap, 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_prog_int = hpc_get_prog_int, 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .query_power_fault = hpc_query_power_fault, 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .green_led_on = hpc_set_green_led_on, 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .green_led_off = hpc_set_green_led_off, 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .green_led_blink = hpc_set_green_led_blink, 9329f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .release_ctlr = hpc_release_ctlr, 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9360abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshigeint shpc_init(struct controller *ctrl, struct pci_dev *pdev) 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 938662a98fb8de5af4adb56e58f78753cdaa27b6459Amol Lad int rc = -1, num_slots = 0; 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 hp_slot; 9400455986cce45d28511f59a29d6cecc17d6b65720Kenji Kaneshige u32 shpc_base_offset; 94175d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige u32 tempdword, slot_reg, slot_config; 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 i; 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9440455986cce45d28511f59a29d6cecc17d6b65720Kenji Kaneshige ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ 945be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, "Hotplug Controller:\n"); 9460455986cce45d28511f59a29d6cecc17d6b65720Kenji Kaneshige 9474cac2eb158c6da0c761689345c6cc5df788a6292Bjorn Helgaas if (pdev->vendor == PCI_VENDOR_ID_AMD && 9484cac2eb158c6da0c761689345c6cc5df788a6292Bjorn Helgaas pdev->device == PCI_DEVICE_ID_AMD_GOLAM_7450) { 9490455986cce45d28511f59a29d6cecc17d6b65720Kenji Kaneshige /* amd shpc driver doesn't use Base Offset; assume 0 */ 9500455986cce45d28511f59a29d6cecc17d6b65720Kenji Kaneshige ctrl->mmio_base = pci_resource_start(pdev, 0); 9510455986cce45d28511f59a29d6cecc17d6b65720Kenji Kaneshige ctrl->mmio_size = pci_resource_len(pdev, 0); 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 9530455986cce45d28511f59a29d6cecc17d6b65720Kenji Kaneshige ctrl->cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC); 9540455986cce45d28511f59a29d6cecc17d6b65720Kenji Kaneshige if (!ctrl->cap_offset) { 955be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "Cannot find PCI capability\n"); 9560abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige goto abort; 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 958be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, " cap_offset = %x\n", ctrl->cap_offset); 9590455986cce45d28511f59a29d6cecc17d6b65720Kenji Kaneshige 96075d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige rc = shpc_indirect_read(ctrl, 0, &shpc_base_offset); 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) { 962be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "Cannot read base_offset\n"); 9630abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige goto abort; 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9650455986cce45d28511f59a29d6cecc17d6b65720Kenji Kaneshige 96675d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige rc = shpc_indirect_read(ctrl, 3, &tempdword); 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) { 968be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "Cannot read slot config\n"); 9690abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige goto abort; 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9710455986cce45d28511f59a29d6cecc17d6b65720Kenji Kaneshige num_slots = tempdword & SLOT_NUM; 972be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, " num_slots (indirect) %x\n", num_slots); 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9740455986cce45d28511f59a29d6cecc17d6b65720Kenji Kaneshige for (i = 0; i < 9 + num_slots; i++) { 97575d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige rc = shpc_indirect_read(ctrl, i, &tempdword); 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) { 977be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, 978be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi "Cannot read creg (index = %d)\n", i); 9790abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige goto abort; 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 981be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, " offset %d: value %x\n", i, tempdword); 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9830455986cce45d28511f59a29d6cecc17d6b65720Kenji Kaneshige 9840455986cce45d28511f59a29d6cecc17d6b65720Kenji Kaneshige ctrl->mmio_base = 9850455986cce45d28511f59a29d6cecc17d6b65720Kenji Kaneshige pci_resource_start(pdev, 0) + shpc_base_offset; 9860455986cce45d28511f59a29d6cecc17d6b65720Kenji Kaneshige ctrl->mmio_size = 0x24 + 0x4 * num_slots; 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 989f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, "HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", 990f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi pdev->vendor, pdev->device, pdev->subsystem_vendor, 991f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi pdev->subsystem_device); 9929f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige 993662a98fb8de5af4adb56e58f78753cdaa27b6459Amol Lad rc = pci_enable_device(pdev); 994662a98fb8de5af4adb56e58f78753cdaa27b6459Amol Lad if (rc) { 995be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "pci_enable_device failed\n"); 9960abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige goto abort; 997662a98fb8de5af4adb56e58f78753cdaa27b6459Amol Lad } 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9990455986cce45d28511f59a29d6cecc17d6b65720Kenji Kaneshige if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) { 1000be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "Cannot reserve MMIO region\n"); 1001662a98fb8de5af4adb56e58f78753cdaa27b6459Amol Lad rc = -1; 10020abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige goto abort; 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10050abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige ctrl->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size); 10060abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige if (!ctrl->creg) { 1007be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_err(ctrl, "Cannot remap MMIO region %lx @ %lx\n", 1008be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl->mmio_size, ctrl->mmio_base); 10090455986cce45d28511f59a29d6cecc17d6b65720Kenji Kaneshige release_mem_region(ctrl->mmio_base, ctrl->mmio_size); 1010662a98fb8de5af4adb56e58f78753cdaa27b6459Amol Lad rc = -1; 10110abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige goto abort; 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1013be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, "ctrl->creg %p\n", ctrl->creg); 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10156aa4cdd07139ba4d5b89139b0070d795cc4dea88Ingo Molnar mutex_init(&ctrl->crit_sect); 1016d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccfKenji Kaneshige mutex_init(&ctrl->cmd_lock); 1017d29aaddab3ef3bdaecf3c9c6d9423f0bf0452ccfKenji Kaneshige 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Setup wait queue */ 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_waitqueue_head(&ctrl->queue); 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 102175d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige ctrl->hpc_ops = &shpchp_hpc_ops; 102275d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Return PCI Controller Info */ 102475d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige slot_config = shpc_readl(ctrl, SLOT_CONFIG); 10250abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige ctrl->slot_device_offset = (slot_config & FIRST_DEV_NUM) >> 8; 10260abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige ctrl->num_slots = slot_config & SLOT_NUM; 10270abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige ctrl->first_slot = (slot_config & PSN) >> 16; 10280abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige ctrl->slot_num_inc = ((slot_config & UPDOWN) >> 29) ? 1 : -1; 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Mask Global Interrupt Mask & Command Complete Interrupt Mask */ 103175d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); 1032be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, "SERR_INTR_ENABLE = %x\n", tempdword); 1033e7138723692e43b7d43578746ad21bf194847527Kenji Kaneshige tempdword |= (GLOBAL_INTR_MASK | GLOBAL_SERR_MASK | 1034e7138723692e43b7d43578746ad21bf194847527Kenji Kaneshige COMMAND_INTR_MASK | ARBITER_SERR_MASK); 1035e7138723692e43b7d43578746ad21bf194847527Kenji Kaneshige tempdword &= ~SERR_INTR_RSVDZ_MASK; 103675d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword); 103775d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); 1038be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, "SERR_INTR_ENABLE = %x\n", tempdword); 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Mask the MRL sensor SERR Mask of individual slot in 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Slot SERR-INT Mask & clear all the existing event if any 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10430abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { 10442b34da7e61383b4b7773d2d4e776e58725794347Kenji Kaneshige slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); 1045be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, "Default Logical Slot Register %d value %x\n", 1046be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi hp_slot, slot_reg); 1047795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK | 1048795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK | 1049795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige CON_PFAULT_INTR_MASK | MRL_CHANGE_SERR_MASK | 1050795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige CON_PFAULT_SERR_MASK); 1051795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige slot_reg &= ~SLOT_REG_RSVDZ_MASK; 1052795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10549f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige 10550abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige if (shpchp_poll_mode) { 10560abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige /* Install interrupt polling timer. Start with 10 sec delay */ 10570abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige init_timer(&ctrl->poll_timer); 10580abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige start_int_poll_timer(ctrl, 10); 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Installs the interrupt handler */ 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = pci_enable_msi(pdev); 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) { 1063f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, 1064f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi "Can't get msi for the hotplug controller\n"); 1065f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_info(ctrl, 1066f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi "Use INTx for the hotplug controller\n"); 10670abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige } 10689f593e30b318719b0e3889c730cc3a2d0729a707Kenji Kaneshige 10690abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED, 10700abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige MY_NAME, (void *)ctrl); 1071e24dcbef93dbbf529fbedfc6ce8ab22d2cef35f0Tejun Heo ctrl_dbg(ctrl, "request_irq %d (returns %d)\n", 1072e24dcbef93dbbf529fbedfc6ce8ab22d2cef35f0Tejun Heo ctrl->pci_dev->irq, rc); 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) { 1074f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi ctrl_err(ctrl, "Can't get irq %d for the hotplug " 1075f98ca311f3a32e2adc229fecd6bf732db07fcca3Taku Izumi "controller\n", ctrl->pci_dev->irq); 10760abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige goto abort_iounmap; 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1079be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, "HPC at %s irq=%x\n", pci_name(pdev), pdev->irq); 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10813749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox shpc_get_max_bus_speed(ctrl); 10823749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox shpc_get_cur_bus_speed(ctrl); 10833749c51ac6c1560aa1cb1520066bed84c6f8152aMatthew Wilcox 1084795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige /* 1085795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige * Unmask all event interrupts of all slots 1086795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige */ 10870abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { 10882b34da7e61383b4b7773d2d4e776e58725794347Kenji Kaneshige slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot)); 1089be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, "Default Logical Slot Register %d value %x\n", 1090be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi hp_slot, slot_reg); 1091795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige slot_reg &= ~(PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK | 1092795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK | 1093795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige CON_PFAULT_INTR_MASK | SLOT_REG_RSVDZ_MASK); 1094795eb5c4a73bee30e8c2dbb29174b329da56051cKenji Kaneshige shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg); 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!shpchp_poll_mode) { 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Unmask all general input interrupts and SERR */ 109875d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); 1099e7138723692e43b7d43578746ad21bf194847527Kenji Kaneshige tempdword &= ~(GLOBAL_INTR_MASK | COMMAND_INTR_MASK | 1100e7138723692e43b7d43578746ad21bf194847527Kenji Kaneshige SERR_INTR_RSVDZ_MASK); 110175d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword); 110275d97c59a192ca0fe2577974dac0c16a73a377ebKenji Kaneshige tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE); 1103be7bce250a88fbbb5a67204eb148bce8b798780aTaku Izumi ctrl_dbg(ctrl, "SERR_INTR_ENABLE = %x\n", tempdword); 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We end up here for the many possible ways to fail this API. */ 11090abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshigeabort_iounmap: 11100abe68ce24973a23fcc6cbce80343f68656de7b6Kenji Kaneshige iounmap(ctrl->creg); 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsabort: 1112662a98fb8de5af4adb56e58f78753cdaa27b6459Amol Lad return rc; 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1114