aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/shpchp_hpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug/shpchp_hpc.c')
-rw-r--r--drivers/pci/hotplug/shpchp_hpc.c861
1 files changed, 378 insertions, 483 deletions
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 66123cf4dea..45facaad39b 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -90,77 +90,94 @@
90#define MRLSENSOR 0x40000000 90#define MRLSENSOR 0x40000000
91#define ATTN_BUTTON 0x80000000 91#define ATTN_BUTTON 0x80000000
92 92
93/* Slot Status Field Definitions */ 93/*
94/* Slot State */ 94 * Interrupt Locator Register definitions
95#define PWR_ONLY 0x0001 95 */
96#define ENABLED 0x0002 96#define CMD_INTR_PENDING (1 << 0)
97#define DISABLED 0x0003 97#define SLOT_INTR_PENDING(i) (1 << (i + 1))
98
99/* Power Indicator State */
100#define PWR_LED_ON 0x0004
101#define PWR_LED_BLINK 0x0008
102#define PWR_LED_OFF 0x000c
103
104/* Attention Indicator State */
105#define ATTEN_LED_ON 0x0010
106#define ATTEN_LED_BLINK 0x0020
107#define ATTEN_LED_OFF 0x0030
108
109/* Power Fault */
110#define pwr_fault 0x0040
111
112/* Attention Button */
113#define ATTEN_BUTTON 0x0080
114
115/* MRL Sensor */
116#define MRL_SENSOR 0x0100
117
118/* 66 MHz Capable */
119#define IS_66MHZ_CAP 0x0200
120
121/* PRSNT1#/PRSNT2# */
122#define SLOT_EMP 0x0c00
123
124/* PCI-X Capability */
125#define NON_PCIX 0x0000
126#define PCIX_66 0x1000
127#define PCIX_133 0x3000
128#define PCIX_266 0x4000 /* For PI = 2 only */
129#define PCIX_533 0x5000 /* For PI = 2 only */
130
131/* SHPC 'write' operations/commands */
132
133/* Slot operation - 0x00h to 0x3Fh */
134
135#define NO_CHANGE 0x00
136
137/* Slot state - Bits 0 & 1 of controller command register */
138#define SET_SLOT_PWR 0x01
139#define SET_SLOT_ENABLE 0x02
140#define SET_SLOT_DISABLE 0x03
141 98
142/* Power indicator state - Bits 2 & 3 of controller command register*/ 99/*
143#define SET_PWR_ON 0x04 100 * Controller SERR-INT Register
144#define SET_PWR_BLINK 0x08 101 */
145#define SET_PWR_OFF 0x0C 102#define GLOBAL_INTR_MASK (1 << 0)
103#define GLOBAL_SERR_MASK (1 << 1)
104#define COMMAND_INTR_MASK (1 << 2)
105#define ARBITER_SERR_MASK (1 << 3)
106#define COMMAND_DETECTED (1 << 16)
107#define ARBITER_DETECTED (1 << 17)
108#define SERR_INTR_RSVDZ_MASK 0xfffc0000
146 109
147/* Attention indicator state - Bits 4 & 5 of controller command register*/ 110/*
148#define SET_ATTN_ON 0x010 111 * Logical Slot Register definitions
149#define SET_ATTN_BLINK 0x020 112 */
150#define SET_ATTN_OFF 0x030 113#define SLOT_REG(i) (SLOT1 + (4 * i))
114
115#define SLOT_STATE_SHIFT (0)
116#define SLOT_STATE_MASK (3 << 0)
117#define SLOT_STATE_PWRONLY (1)
118#define SLOT_STATE_ENABLED (2)
119#define SLOT_STATE_DISABLED (3)
120#define PWR_LED_STATE_SHIFT (2)
121#define PWR_LED_STATE_MASK (3 << 2)
122#define ATN_LED_STATE_SHIFT (4)
123#define ATN_LED_STATE_MASK (3 << 4)
124#define ATN_LED_STATE_ON (1)
125#define ATN_LED_STATE_BLINK (2)
126#define ATN_LED_STATE_OFF (3)
127#define POWER_FAULT (1 << 6)
128#define ATN_BUTTON (1 << 7)
129#define MRL_SENSOR (1 << 8)
130#define MHZ66_CAP (1 << 9)
131#define PRSNT_SHIFT (10)
132#define PRSNT_MASK (3 << 10)
133#define PCIX_CAP_SHIFT (12)
134#define PCIX_CAP_MASK_PI1 (3 << 12)
135#define PCIX_CAP_MASK_PI2 (7 << 12)
136#define PRSNT_CHANGE_DETECTED (1 << 16)
137#define ISO_PFAULT_DETECTED (1 << 17)
138#define BUTTON_PRESS_DETECTED (1 << 18)
139#define MRL_CHANGE_DETECTED (1 << 19)
140#define CON_PFAULT_DETECTED (1 << 20)
141#define PRSNT_CHANGE_INTR_MASK (1 << 24)
142#define ISO_PFAULT_INTR_MASK (1 << 25)
143#define BUTTON_PRESS_INTR_MASK (1 << 26)
144#define MRL_CHANGE_INTR_MASK (1 << 27)
145#define CON_PFAULT_INTR_MASK (1 << 28)
146#define MRL_CHANGE_SERR_MASK (1 << 29)
147#define CON_PFAULT_SERR_MASK (1 << 30)
148#define SLOT_REG_RSVDZ_MASK (1 << 15) | (7 << 21)
151 149
152/* Set bus speed/mode A - 0x40h to 0x47h */ 150/*
153#define SETA_PCI_33MHZ 0x40 151 * SHPC Command Code definitnions
152 *
153 * Slot Operation 00h - 3Fh
154 * Set Bus Segment Speed/Mode A 40h - 47h
155 * Power-Only All Slots 48h
156 * Enable All Slots 49h
157 * Set Bus Segment Speed/Mode B (PI=2) 50h - 5Fh
158 * Reserved Command Codes 60h - BFh
159 * Vendor Specific Commands C0h - FFh
160 */
161#define SET_SLOT_PWR 0x01 /* Slot Operation */
162#define SET_SLOT_ENABLE 0x02
163#define SET_SLOT_DISABLE 0x03
164#define SET_PWR_ON 0x04
165#define SET_PWR_BLINK 0x08
166#define SET_PWR_OFF 0x0c
167#define SET_ATTN_ON 0x10
168#define SET_ATTN_BLINK 0x20
169#define SET_ATTN_OFF 0x30
170#define SETA_PCI_33MHZ 0x40 /* Set Bus Segment Speed/Mode A */
154#define SETA_PCI_66MHZ 0x41 171#define SETA_PCI_66MHZ 0x41
155#define SETA_PCIX_66MHZ 0x42 172#define SETA_PCIX_66MHZ 0x42
156#define SETA_PCIX_100MHZ 0x43 173#define SETA_PCIX_100MHZ 0x43
157#define SETA_PCIX_133MHZ 0x44 174#define SETA_PCIX_133MHZ 0x44
158#define RESERV_1 0x45 175#define SETA_RESERVED1 0x45
159#define RESERV_2 0x46 176#define SETA_RESERVED2 0x46
160#define RESERV_3 0x47 177#define SETA_RESERVED3 0x47
161 178#define SET_PWR_ONLY_ALL 0x48 /* Power-Only All Slots */
162/* Set bus speed/mode B - 0x50h to 0x5fh */ 179#define SET_ENABLE_ALL 0x49 /* Enable All Slots */
163#define SETB_PCI_33MHZ 0x50 180#define SETB_PCI_33MHZ 0x50 /* Set Bus Segment Speed/Mode B */
164#define SETB_PCI_66MHZ 0x51 181#define SETB_PCI_66MHZ 0x51
165#define SETB_PCIX_66MHZ_PM 0x52 182#define SETB_PCIX_66MHZ_PM 0x52
166#define SETB_PCIX_100MHZ_PM 0x53 183#define SETB_PCIX_100MHZ_PM 0x53
@@ -174,81 +191,115 @@
174#define SETB_PCIX_66MHZ_533 0x5b 191#define SETB_PCIX_66MHZ_533 0x5b
175#define SETB_PCIX_100MHZ_533 0x5c 192#define SETB_PCIX_100MHZ_533 0x5c
176#define SETB_PCIX_133MHZ_533 0x5d 193#define SETB_PCIX_133MHZ_533 0x5d
194#define SETB_RESERVED1 0x5e
195#define SETB_RESERVED2 0x5f
177 196
178 197/*
179/* Power-on all slots - 0x48h */ 198 * SHPC controller command error code
180#define SET_PWR_ON_ALL 0x48 199 */
181
182/* Enable all slots - 0x49h */
183#define SET_ENABLE_ALL 0x49
184
185/* SHPC controller command error code */
186#define SWITCH_OPEN 0x1 200#define SWITCH_OPEN 0x1
187#define INVALID_CMD 0x2 201#define INVALID_CMD 0x2
188#define INVALID_SPEED_MODE 0x4 202#define INVALID_SPEED_MODE 0x4
189 203
190/* For accessing SHPC Working Register Set */ 204/*
205 * For accessing SHPC Working Register Set via PCI Configuration Space
206 */
191#define DWORD_SELECT 0x2 207#define DWORD_SELECT 0x2
192#define DWORD_DATA 0x4 208#define DWORD_DATA 0x4
193#define BASE_OFFSET 0x0
194 209
195/* Field Offset in Logical Slot Register - byte boundary */ 210/* Field Offset in Logical Slot Register - byte boundary */
196#define SLOT_EVENT_LATCH 0x2 211#define SLOT_EVENT_LATCH 0x2
197#define SLOT_SERR_INT_MASK 0x3 212#define SLOT_SERR_INT_MASK 0x3
198 213
199static spinlock_t hpc_event_lock;
200
201DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ 214DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */
202static struct php_ctlr_state_s *php_ctlr_list_head; /* HPC state linked list */ 215static struct php_ctlr_state_s *php_ctlr_list_head; /* HPC state linked list */
203static int ctlr_seq_num = 0; /* Controller sequenc # */ 216static int ctlr_seq_num = 0; /* Controller sequenc # */
204static spinlock_t list_lock; 217static spinlock_t list_lock;
205 218
206static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs); 219static atomic_t shpchp_num_controllers = ATOMIC_INIT(0);
207 220
208static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds); 221static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs);
222static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec);
209static int hpc_check_cmd_status(struct controller *ctrl); 223static int hpc_check_cmd_status(struct controller *ctrl);
210 224
211/* This is the interrupt polling timeout function. */ 225static inline u8 shpc_readb(struct controller *ctrl, int reg)
212static void int_poll_timeout(unsigned long lphp_ctlr)
213{ 226{
214 struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *)lphp_ctlr; 227 return readb(ctrl->hpc_ctlr_handle->creg + reg);
228}
215 229
216 DBG_ENTER_ROUTINE 230static inline void shpc_writeb(struct controller *ctrl, int reg, u8 val)
231{
232 writeb(val, ctrl->hpc_ctlr_handle->creg + reg);
233}
217 234
218 if ( !php_ctlr ) { 235static inline u16 shpc_readw(struct controller *ctrl, int reg)
219 err("%s: Invalid HPC controller handle!\n", __FUNCTION__); 236{
220 return; 237 return readw(ctrl->hpc_ctlr_handle->creg + reg);
221 } 238}
222 239
223 /* Poll for interrupt events. regs == NULL => polling */ 240static inline void shpc_writew(struct controller *ctrl, int reg, u16 val)
224 shpc_isr( 0, (void *)php_ctlr, NULL ); 241{
242 writew(val, ctrl->hpc_ctlr_handle->creg + reg);
243}
225 244
226 init_timer(&php_ctlr->int_poll_timer); 245static inline u32 shpc_readl(struct controller *ctrl, int reg)
227 if (!shpchp_poll_time) 246{
228 shpchp_poll_time = 2; /* reset timer to poll in 2 secs if user doesn't specify at module installation*/ 247 return readl(ctrl->hpc_ctlr_handle->creg + reg);
248}
229 249
230 start_int_poll_timer(php_ctlr, shpchp_poll_time); 250static inline void shpc_writel(struct controller *ctrl, int reg, u32 val)
231 251{
232 return; 252 writel(val, ctrl->hpc_ctlr_handle->creg + reg);
233} 253}
234 254
235/* This function starts the interrupt polling timer. */ 255static inline int shpc_indirect_read(struct controller *ctrl, int index,
236static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds) 256 u32 *value)
237{ 257{
238 if (!php_ctlr) { 258 int rc;
239 err("%s: Invalid HPC controller handle!\n", __FUNCTION__); 259 u32 cap_offset = ctrl->cap_offset;
240 return; 260 struct pci_dev *pdev = ctrl->pci_dev;
241 } 261
262 rc = pci_write_config_byte(pdev, cap_offset + DWORD_SELECT, index);
263 if (rc)
264 return rc;
265 return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value);
266}
267
268/*
269 * This is the interrupt polling timeout function.
270 */
271static void int_poll_timeout(unsigned long lphp_ctlr)
272{
273 struct php_ctlr_state_s *php_ctlr =
274 (struct php_ctlr_state_s *)lphp_ctlr;
275
276 DBG_ENTER_ROUTINE
277
278 /* Poll for interrupt events. regs == NULL => polling */
279 shpc_isr(0, php_ctlr->callback_instance_id, NULL);
280
281 init_timer(&php_ctlr->int_poll_timer);
282 if (!shpchp_poll_time)
283 shpchp_poll_time = 2; /* default polling interval is 2 sec */
242 284
243 if ( ( seconds <= 0 ) || ( seconds > 60 ) ) 285 start_int_poll_timer(php_ctlr, shpchp_poll_time);
244 seconds = 2; /* Clamp to sane value */
245 286
246 php_ctlr->int_poll_timer.function = &int_poll_timeout; 287 DBG_LEAVE_ROUTINE
247 php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr; /* Instance data */ 288}
248 php_ctlr->int_poll_timer.expires = jiffies + seconds * HZ;
249 add_timer(&php_ctlr->int_poll_timer);
250 289
251 return; 290/*
291 * This function starts the interrupt polling timer.
292 */
293static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec)
294{
295 /* Clamp to sane value */
296 if ((sec <= 0) || (sec > 60))
297 sec = 2;
298
299 php_ctlr->int_poll_timer.function = &int_poll_timeout;
300 php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr;
301 php_ctlr->int_poll_timer.expires = jiffies + sec * HZ;
302 add_timer(&php_ctlr->int_poll_timer);
252} 303}
253 304
254static inline int shpc_wait_cmd(struct controller *ctrl) 305static inline int shpc_wait_cmd(struct controller *ctrl)
@@ -272,7 +323,7 @@ static inline int shpc_wait_cmd(struct controller *ctrl)
272 323
273static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) 324static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
274{ 325{
275 struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; 326 struct controller *ctrl = slot->ctrl;
276 u16 cmd_status; 327 u16 cmd_status;
277 int retval = 0; 328 int retval = 0;
278 u16 temp_word; 329 u16 temp_word;
@@ -282,14 +333,8 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
282 333
283 mutex_lock(&slot->ctrl->cmd_lock); 334 mutex_lock(&slot->ctrl->cmd_lock);
284 335
285 if (!php_ctlr) {
286 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
287 retval = -EINVAL;
288 goto out;
289 }
290
291 for (i = 0; i < 10; i++) { 336 for (i = 0; i < 10; i++) {
292 cmd_status = readw(php_ctlr->creg + CMD_STATUS); 337 cmd_status = shpc_readw(ctrl, CMD_STATUS);
293 338
294 if (!(cmd_status & 0x1)) 339 if (!(cmd_status & 0x1))
295 break; 340 break;
@@ -297,7 +342,7 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
297 msleep(100); 342 msleep(100);
298 } 343 }
299 344
300 cmd_status = readw(php_ctlr->creg + CMD_STATUS); 345 cmd_status = shpc_readw(ctrl, CMD_STATUS);
301 346
302 if (cmd_status & 0x1) { 347 if (cmd_status & 0x1) {
303 /* After 1 sec and and the controller is still busy */ 348 /* After 1 sec and and the controller is still busy */
@@ -314,7 +359,7 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
314 * command. 359 * command.
315 */ 360 */
316 slot->ctrl->cmd_busy = 1; 361 slot->ctrl->cmd_busy = 1;
317 writew(temp_word, php_ctlr->creg + CMD); 362 shpc_writew(ctrl, CMD, temp_word);
318 363
319 /* 364 /*
320 * Wait for command completion. 365 * Wait for command completion.
@@ -338,18 +383,12 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
338 383
339static int hpc_check_cmd_status(struct controller *ctrl) 384static int hpc_check_cmd_status(struct controller *ctrl)
340{ 385{
341 struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
342 u16 cmd_status; 386 u16 cmd_status;
343 int retval = 0; 387 int retval = 0;
344 388
345 DBG_ENTER_ROUTINE 389 DBG_ENTER_ROUTINE
346
347 if (!ctrl->hpc_ctlr_handle) {
348 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
349 return -1;
350 }
351 390
352 cmd_status = readw(php_ctlr->creg + CMD_STATUS) & 0x000F; 391 cmd_status = shpc_readw(ctrl, CMD_STATUS) & 0x000F;
353 392
354 switch (cmd_status >> 1) { 393 switch (cmd_status >> 1) {
355 case 0: 394 case 0:
@@ -378,37 +417,27 @@ static int hpc_check_cmd_status(struct controller *ctrl)
378 417
379static int hpc_get_attention_status(struct slot *slot, u8 *status) 418static int hpc_get_attention_status(struct slot *slot, u8 *status)
380{ 419{
381 struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; 420 struct controller *ctrl = slot->ctrl;
382 u32 slot_reg; 421 u32 slot_reg;
383 u16 slot_status; 422 u8 state;
384 u8 atten_led_state;
385 423
386 DBG_ENTER_ROUTINE 424 DBG_ENTER_ROUTINE
387 425
388 if (!slot->ctrl->hpc_ctlr_handle) { 426 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
389 err("%s: Invalid HPC controller handle!\n", __FUNCTION__); 427 state = (slot_reg & ATN_LED_STATE_MASK) >> ATN_LED_STATE_SHIFT;
390 return -1;
391 }
392
393 slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
394 slot_status = (u16) slot_reg;
395 atten_led_state = (slot_status & 0x0030) >> 4;
396 428
397 switch (atten_led_state) { 429 switch (state) {
398 case 0: 430 case ATN_LED_STATE_ON:
399 *status = 0xFF; /* Reserved */
400 break;
401 case 1:
402 *status = 1; /* On */ 431 *status = 1; /* On */
403 break; 432 break;
404 case 2: 433 case ATN_LED_STATE_BLINK:
405 *status = 2; /* Blink */ 434 *status = 2; /* Blink */
406 break; 435 break;
407 case 3: 436 case ATN_LED_STATE_OFF:
408 *status = 0; /* Off */ 437 *status = 0; /* Off */
409 break; 438 break;
410 default: 439 default:
411 *status = 0xFF; 440 *status = 0xFF; /* Reserved */
412 break; 441 break;
413 } 442 }
414 443
@@ -418,64 +447,44 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)
418 447
419static int hpc_get_power_status(struct slot * slot, u8 *status) 448static int hpc_get_power_status(struct slot * slot, u8 *status)
420{ 449{
421 struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; 450 struct controller *ctrl = slot->ctrl;
422 u32 slot_reg; 451 u32 slot_reg;
423 u16 slot_status; 452 u8 state;
424 u8 slot_state;
425 int retval = 0;
426 453
427 DBG_ENTER_ROUTINE 454 DBG_ENTER_ROUTINE
428 455
429 if (!slot->ctrl->hpc_ctlr_handle) { 456 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
430 err("%s: Invalid HPC controller handle!\n", __FUNCTION__); 457 state = (slot_reg & SLOT_STATE_MASK) >> SLOT_STATE_SHIFT;
431 return -1;
432 }
433
434 slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
435 slot_status = (u16) slot_reg;
436 slot_state = (slot_status & 0x0003);
437 458
438 switch (slot_state) { 459 switch (state) {
439 case 0: 460 case SLOT_STATE_PWRONLY:
440 *status = 0xFF;
441 break;
442 case 1:
443 *status = 2; /* Powered only */ 461 *status = 2; /* Powered only */
444 break; 462 break;
445 case 2: 463 case SLOT_STATE_ENABLED:
446 *status = 1; /* Enabled */ 464 *status = 1; /* Enabled */
447 break; 465 break;
448 case 3: 466 case SLOT_STATE_DISABLED:
449 *status = 0; /* Disabled */ 467 *status = 0; /* Disabled */
450 break; 468 break;
451 default: 469 default:
452 *status = 0xFF; 470 *status = 0xFF; /* Reserved */
453 break; 471 break;
454 } 472 }
455 473
456 DBG_LEAVE_ROUTINE 474 DBG_LEAVE_ROUTINE
457 return retval; 475 return 0;
458} 476}
459 477
460 478
461static int hpc_get_latch_status(struct slot *slot, u8 *status) 479static int hpc_get_latch_status(struct slot *slot, u8 *status)
462{ 480{
463 struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; 481 struct controller *ctrl = slot->ctrl;
464 u32 slot_reg; 482 u32 slot_reg;
465 u16 slot_status;
466 483
467 DBG_ENTER_ROUTINE 484 DBG_ENTER_ROUTINE
468 485
469 if (!slot->ctrl->hpc_ctlr_handle) { 486 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
470 err("%s: Invalid HPC controller handle!\n", __FUNCTION__); 487 *status = !!(slot_reg & MRL_SENSOR); /* 0 -> close; 1 -> open */
471 return -1;
472 }
473
474 slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
475 slot_status = (u16)slot_reg;
476
477 *status = ((slot_status & 0x0100) == 0) ? 0 : 1; /* 0 -> close; 1 -> open */
478
479 488
480 DBG_LEAVE_ROUTINE 489 DBG_LEAVE_ROUTINE
481 return 0; 490 return 0;
@@ -483,22 +492,15 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status)
483 492
484static int hpc_get_adapter_status(struct slot *slot, u8 *status) 493static int hpc_get_adapter_status(struct slot *slot, u8 *status)
485{ 494{
486 struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; 495 struct controller *ctrl = slot->ctrl;
487 u32 slot_reg; 496 u32 slot_reg;
488 u16 slot_status; 497 u8 state;
489 u8 card_state;
490 498
491 DBG_ENTER_ROUTINE 499 DBG_ENTER_ROUTINE
492 500
493 if (!slot->ctrl->hpc_ctlr_handle) { 501 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
494 err("%s: Invalid HPC controller handle!\n", __FUNCTION__); 502 state = (slot_reg & PRSNT_MASK) >> PRSNT_SHIFT;
495 return -1; 503 *status = (state != 0x3) ? 1 : 0;
496 }
497
498 slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
499 slot_status = (u16)slot_reg;
500 card_state = (u8)((slot_status & 0x0C00) >> 10);
501 *status = (card_state != 0x3) ? 1 : 0;
502 504
503 DBG_LEAVE_ROUTINE 505 DBG_LEAVE_ROUTINE
504 return 0; 506 return 0;
@@ -506,16 +508,11 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status)
506 508
507static int hpc_get_prog_int(struct slot *slot, u8 *prog_int) 509static int hpc_get_prog_int(struct slot *slot, u8 *prog_int)
508{ 510{
509 struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; 511 struct controller *ctrl = slot->ctrl;
510 512
511 DBG_ENTER_ROUTINE 513 DBG_ENTER_ROUTINE
512
513 if (!slot->ctrl->hpc_ctlr_handle) {
514 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
515 return -1;
516 }
517 514
518 *prog_int = readb(php_ctlr->creg + PROG_INTERFACE); 515 *prog_int = shpc_readb(ctrl, PROG_INTERFACE);
519 516
520 DBG_LEAVE_ROUTINE 517 DBG_LEAVE_ROUTINE
521 return 0; 518 return 0;
@@ -524,13 +521,27 @@ static int hpc_get_prog_int(struct slot *slot, u8 *prog_int)
524static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) 521static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
525{ 522{
526 int retval = 0; 523 int retval = 0;
527 struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; 524 struct controller *ctrl = slot->ctrl;
528 u32 slot_reg = readl(php_ctlr->creg + SLOT1 + 4 * slot->hp_slot); 525 u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
529 u8 pcix_cap = (slot_reg >> 12) & 7; 526 u8 m66_cap = !!(slot_reg & MHZ66_CAP);
530 u8 m66_cap = (slot_reg >> 9) & 1; 527 u8 pi, pcix_cap;
531 528
532 DBG_ENTER_ROUTINE 529 DBG_ENTER_ROUTINE
533 530
531 if ((retval = hpc_get_prog_int(slot, &pi)))
532 return retval;
533
534 switch (pi) {
535 case 1:
536 pcix_cap = (slot_reg & PCIX_CAP_MASK_PI1) >> PCIX_CAP_SHIFT;
537 break;
538 case 2:
539 pcix_cap = (slot_reg & PCIX_CAP_MASK_PI2) >> PCIX_CAP_SHIFT;
540 break;
541 default:
542 return -ENODEV;
543 }
544
534 dbg("%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n", 545 dbg("%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n",
535 __FUNCTION__, slot_reg, pcix_cap, m66_cap); 546 __FUNCTION__, slot_reg, pcix_cap, m66_cap);
536 547
@@ -564,20 +575,15 @@ static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
564 575
565static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode) 576static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)
566{ 577{
567 struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; 578 struct controller *ctrl = slot->ctrl;
568 u16 sec_bus_status; 579 u16 sec_bus_status;
569 u8 pi; 580 u8 pi;
570 int retval = 0; 581 int retval = 0;
571 582
572 DBG_ENTER_ROUTINE 583 DBG_ENTER_ROUTINE
573 584
574 if (!slot->ctrl->hpc_ctlr_handle) { 585 pi = shpc_readb(ctrl, PROG_INTERFACE);
575 err("%s: Invalid HPC controller handle!\n", __FUNCTION__); 586 sec_bus_status = shpc_readw(ctrl, SEC_BUS_CONFIG);
576 return -1;
577 }
578
579 pi = readb(php_ctlr->creg + PROG_INTERFACE);
580 sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG);
581 587
582 if (pi == 2) { 588 if (pi == 2) {
583 *mode = (sec_bus_status & 0x0100) >> 8; 589 *mode = (sec_bus_status & 0x0100) >> 8;
@@ -593,128 +599,53 @@ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)
593 599
594static int hpc_query_power_fault(struct slot * slot) 600static int hpc_query_power_fault(struct slot * slot)
595{ 601{
596 struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; 602 struct controller *ctrl = slot->ctrl;
597 u32 slot_reg; 603 u32 slot_reg;
598 u16 slot_status;
599 u8 pwr_fault_state, status;
600 604
601 DBG_ENTER_ROUTINE 605 DBG_ENTER_ROUTINE
602 606
603 if (!slot->ctrl->hpc_ctlr_handle) { 607 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
604 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
605 return -1;
606 }
607
608 slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
609 slot_status = (u16) slot_reg;
610 pwr_fault_state = (slot_status & 0x0040) >> 7;
611 status = (pwr_fault_state == 1) ? 0 : 1;
612 608
613 DBG_LEAVE_ROUTINE 609 DBG_LEAVE_ROUTINE
614 /* Note: Logic 0 => fault */ 610 /* Note: Logic 0 => fault */
615 return status; 611 return !(slot_reg & POWER_FAULT);
616} 612}
617 613
618static int hpc_set_attention_status(struct slot *slot, u8 value) 614static int hpc_set_attention_status(struct slot *slot, u8 value)
619{ 615{
620 struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
621 u8 slot_cmd = 0; 616 u8 slot_cmd = 0;
622 int rc = 0;
623
624 if (!slot->ctrl->hpc_ctlr_handle) {
625 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
626 return -1;
627 }
628
629 if (slot->hp_slot >= php_ctlr->num_slots) {
630 err("%s: Invalid HPC slot number!\n", __FUNCTION__);
631 return -1;
632 }
633 617
634 switch (value) { 618 switch (value) {
635 case 0 : 619 case 0 :
636 slot_cmd = 0x30; /* OFF */ 620 slot_cmd = SET_ATTN_OFF; /* OFF */
637 break; 621 break;
638 case 1: 622 case 1:
639 slot_cmd = 0x10; /* ON */ 623 slot_cmd = SET_ATTN_ON; /* ON */
640 break; 624 break;
641 case 2: 625 case 2:
642 slot_cmd = 0x20; /* BLINK */ 626 slot_cmd = SET_ATTN_BLINK; /* BLINK */
643 break; 627 break;
644 default: 628 default:
645 return -1; 629 return -1;
646 } 630 }
647 631
648 shpc_write_cmd(slot, slot->hp_slot, slot_cmd); 632 return shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
649
650 return rc;
651} 633}
652 634
653 635
654static void hpc_set_green_led_on(struct slot *slot) 636static void hpc_set_green_led_on(struct slot *slot)
655{ 637{
656 struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; 638 shpc_write_cmd(slot, slot->hp_slot, SET_PWR_ON);
657 u8 slot_cmd;
658
659 if (!slot->ctrl->hpc_ctlr_handle) {
660 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
661 return ;
662 }
663
664 if (slot->hp_slot >= php_ctlr->num_slots) {
665 err("%s: Invalid HPC slot number!\n", __FUNCTION__);
666 return ;
667 }
668
669 slot_cmd = 0x04;
670
671 shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
672
673 return;
674} 639}
675 640
676static void hpc_set_green_led_off(struct slot *slot) 641static void hpc_set_green_led_off(struct slot *slot)
677{ 642{
678 struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; 643 shpc_write_cmd(slot, slot->hp_slot, SET_PWR_OFF);
679 u8 slot_cmd;
680
681 if (!slot->ctrl->hpc_ctlr_handle) {
682 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
683 return ;
684 }
685
686 if (slot->hp_slot >= php_ctlr->num_slots) {
687 err("%s: Invalid HPC slot number!\n", __FUNCTION__);
688 return ;
689 }
690
691 slot_cmd = 0x0C;
692
693 shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
694
695 return;
696} 644}
697 645
698static void hpc_set_green_led_blink(struct slot *slot) 646static void hpc_set_green_led_blink(struct slot *slot)
699{ 647{
700 struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; 648 shpc_write_cmd(slot, slot->hp_slot, SET_PWR_BLINK);
701 u8 slot_cmd;
702
703 if (!slot->ctrl->hpc_ctlr_handle) {
704 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
705 return ;
706 }
707
708 if (slot->hp_slot >= php_ctlr->num_slots) {
709 err("%s: Invalid HPC slot number!\n", __FUNCTION__);
710 return ;
711 }
712
713 slot_cmd = 0x08;
714
715 shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
716
717 return;
718} 649}
719 650
720int shpc_get_ctlr_slot_config(struct controller *ctrl, 651int shpc_get_ctlr_slot_config(struct controller *ctrl,
@@ -724,21 +655,17 @@ int shpc_get_ctlr_slot_config(struct controller *ctrl,
724 int *updown, /* physical_slot_num increament: 1 or -1 */ 655 int *updown, /* physical_slot_num increament: 1 or -1 */
725 int *flags) 656 int *flags)
726{ 657{
727 struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; 658 u32 slot_config;
728 659
729 DBG_ENTER_ROUTINE 660 DBG_ENTER_ROUTINE
730 661
731 if (!ctrl->hpc_ctlr_handle) { 662 slot_config = shpc_readl(ctrl, SLOT_CONFIG);
732 err("%s: Invalid HPC controller handle!\n", __FUNCTION__); 663 *first_device_num = (slot_config & FIRST_DEV_NUM) >> 8;
733 return -1; 664 *num_ctlr_slots = slot_config & SLOT_NUM;
734 } 665 *physical_slot_num = (slot_config & PSN) >> 16;
735 666 *updown = ((slot_config & UPDOWN) >> 29) ? 1 : -1;
736 *first_device_num = php_ctlr->slot_device_offset; /* Obtained in shpc_init() */
737 *num_ctlr_slots = php_ctlr->num_slots; /* Obtained in shpc_init() */
738 667
739 *physical_slot_num = (readl(php_ctlr->creg + SLOT_CONFIG) & PSN) >> 16;
740 dbg("%s: physical_slot_num = %x\n", __FUNCTION__, *physical_slot_num); 668 dbg("%s: physical_slot_num = %x\n", __FUNCTION__, *physical_slot_num);
741 *updown = ((readl(php_ctlr->creg + SLOT_CONFIG) & UPDOWN ) >> 29) ? 1 : -1;
742 669
743 DBG_LEAVE_ROUTINE 670 DBG_LEAVE_ROUTINE
744 return 0; 671 return 0;
@@ -749,22 +676,34 @@ static void hpc_release_ctlr(struct controller *ctrl)
749 struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; 676 struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
750 struct php_ctlr_state_s *p, *p_prev; 677 struct php_ctlr_state_s *p, *p_prev;
751 int i; 678 int i;
679 u32 slot_reg, serr_int;
752 680
753 DBG_ENTER_ROUTINE 681 DBG_ENTER_ROUTINE
754 682
755 if (!ctrl->hpc_ctlr_handle) {
756 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
757 return ;
758 }
759
760 /* 683 /*
761 * Mask all slot event interrupts 684 * Mask event interrupts and SERRs of all slots
762 */ 685 */
763 for (i = 0; i < ctrl->num_slots; i++) 686 for (i = 0; i < ctrl->num_slots; i++) {
764 writel(0xffff3fff, php_ctlr->creg + SLOT1 + (4 * i)); 687 slot_reg = shpc_readl(ctrl, SLOT_REG(i));
688 slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
689 BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
690 CON_PFAULT_INTR_MASK | MRL_CHANGE_SERR_MASK |
691 CON_PFAULT_SERR_MASK);
692 slot_reg &= ~SLOT_REG_RSVDZ_MASK;
693 shpc_writel(ctrl, SLOT_REG(i), slot_reg);
694 }
765 695
766 cleanup_slots(ctrl); 696 cleanup_slots(ctrl);
767 697
698 /*
699 * Mask SERR and System Interrut generation
700 */
701 serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
702 serr_int |= (GLOBAL_INTR_MASK | GLOBAL_SERR_MASK |
703 COMMAND_INTR_MASK | ARBITER_SERR_MASK);
704 serr_int &= ~SERR_INTR_RSVDZ_MASK;
705 shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
706
768 if (shpchp_poll_mode) { 707 if (shpchp_poll_mode) {
769 del_timer(&php_ctlr->int_poll_timer); 708 del_timer(&php_ctlr->int_poll_timer);
770 } else { 709 } else {
@@ -800,113 +739,79 @@ static void hpc_release_ctlr(struct controller *ctrl)
800 739
801 kfree(php_ctlr); 740 kfree(php_ctlr);
802 741
742 /*
743 * If this is the last controller to be released, destroy the
744 * shpchpd work queue
745 */
746 if (atomic_dec_and_test(&shpchp_num_controllers))
747 destroy_workqueue(shpchp_wq);
748
803DBG_LEAVE_ROUTINE 749DBG_LEAVE_ROUTINE
804 750
805} 751}
806 752
807static int hpc_power_on_slot(struct slot * slot) 753static int hpc_power_on_slot(struct slot * slot)
808{ 754{
809 struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; 755 int retval;
810 u8 slot_cmd;
811 int retval = 0;
812 756
813 DBG_ENTER_ROUTINE 757 DBG_ENTER_ROUTINE
814 758
815 if (!slot->ctrl->hpc_ctlr_handle) { 759 retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_PWR);
816 err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
817 return -1;
818 }
819
820 if (slot->hp_slot >= php_ctlr->num_slots) {
821 err("%s: Invalid HPC slot number!\n", __FUNCTION__);
822 return -1;
823 }
824 slot_cmd = 0x01;
825
826 retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
827
828 if (retval) { 760 if (retval) {
829 err("%s: Write command failed!\n", __FUNCTION__); 761 err("%s: Write command failed!\n", __FUNCTION__);
830 return -1; 762 return retval;
831 } 763 }
832 764
833 DBG_LEAVE_ROUTINE 765 DBG_LEAVE_ROUTINE
834 766
835 return retval; 767 return 0;
836} 768}
837 769
838static int hpc_slot_enable(struct slot * slot) 770static int hpc_slot_enable(struct slot * slot)
839{ 771{
840 struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; 772 int retval;
841 u8 slot_cmd;
842 int retval = 0;
843 773
844 DBG_ENTER_ROUTINE 774 DBG_ENTER_ROUTINE
845 775
846 if (!slot->ctrl->hpc_ctlr_handle) { 776 /* Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */
847 err("%s: Invalid HPC controller handle!\n", __FUNCTION__); 777 retval = shpc_write_cmd(slot, slot->hp_slot,
848 return -1; 778 SET_SLOT_ENABLE | SET_PWR_BLINK | SET_ATTN_OFF);
849 }
850
851 if (slot->hp_slot >= php_ctlr->num_slots) {
852 err("%s: Invalid HPC slot number!\n", __FUNCTION__);
853 return -1;
854 }
855 /* 3A => Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */
856 slot_cmd = 0x3A;
857
858 retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
859
860 if (retval) { 779 if (retval) {
861 err("%s: Write command failed!\n", __FUNCTION__); 780 err("%s: Write command failed!\n", __FUNCTION__);
862 return -1; 781 return retval;
863 } 782 }
864 783
865 DBG_LEAVE_ROUTINE 784 DBG_LEAVE_ROUTINE
866 return retval; 785 return 0;
867} 786}
868 787
869static int hpc_slot_disable(struct slot * slot) 788static int hpc_slot_disable(struct slot * slot)
870{ 789{
871 struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; 790 int retval;
872 u8 slot_cmd;
873 int retval = 0;
874 791
875 DBG_ENTER_ROUTINE 792 DBG_ENTER_ROUTINE
876 793
877 if (!slot->ctrl->hpc_ctlr_handle) { 794 /* Slot - Disable, Power Indicator - Off, Attention Indicator - On */
878 err("%s: Invalid HPC controller handle!\n", __FUNCTION__); 795 retval = shpc_write_cmd(slot, slot->hp_slot,
879 return -1; 796 SET_SLOT_DISABLE | SET_PWR_OFF | SET_ATTN_ON);
880 }
881
882 if (slot->hp_slot >= php_ctlr->num_slots) {
883 err("%s: Invalid HPC slot number!\n", __FUNCTION__);
884 return -1;
885 }
886
887 /* 1F => Slot - Disable, Power Indicator - Off, Attention Indicator - On */
888 slot_cmd = 0x1F;
889
890 retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
891
892 if (retval) { 797 if (retval) {
893 err("%s: Write command failed!\n", __FUNCTION__); 798 err("%s: Write command failed!\n", __FUNCTION__);
894 return -1; 799 return retval;
895 } 800 }
896 801
897 DBG_LEAVE_ROUTINE 802 DBG_LEAVE_ROUTINE
898 return retval; 803 return 0;
899} 804}
900 805
901static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) 806static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
902{ 807{
903 int retval; 808 int retval;
904 struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; 809 struct controller *ctrl = slot->ctrl;
905 u8 pi, cmd; 810 u8 pi, cmd;
906 811
907 DBG_ENTER_ROUTINE 812 DBG_ENTER_ROUTINE
908 813
909 pi = readb(php_ctlr->creg + PROG_INTERFACE); 814 pi = shpc_readb(ctrl, PROG_INTERFACE);
910 if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX)) 815 if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX))
911 return -EINVAL; 816 return -EINVAL;
912 817
@@ -965,100 +870,86 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
965 return retval; 870 return retval;
966} 871}
967 872
968static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) 873static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs)
969{ 874{
970 struct controller *ctrl = NULL; 875 struct controller *ctrl = (struct controller *)dev_id;
971 struct php_ctlr_state_s *php_ctlr; 876 struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
972 u8 schedule_flag = 0; 877 u32 serr_int, slot_reg, intr_loc, intr_loc2;
973 u8 temp_byte;
974 u32 temp_dword, intr_loc, intr_loc2;
975 int hp_slot; 878 int hp_slot;
976 879
977 if (!dev_id)
978 return IRQ_NONE;
979
980 if (!shpchp_poll_mode) {
981 ctrl = (struct controller *)dev_id;
982 php_ctlr = ctrl->hpc_ctlr_handle;
983 } else {
984 php_ctlr = (struct php_ctlr_state_s *) dev_id;
985 ctrl = (struct controller *)php_ctlr->callback_instance_id;
986 }
987
988 if (!ctrl)
989 return IRQ_NONE;
990
991 if (!php_ctlr || !php_ctlr->creg)
992 return IRQ_NONE;
993
994 /* Check to see if it was our interrupt */ 880 /* Check to see if it was our interrupt */
995 intr_loc = readl(php_ctlr->creg + INTR_LOC); 881 intr_loc = shpc_readl(ctrl, INTR_LOC);
996
997 if (!intr_loc) 882 if (!intr_loc)
998 return IRQ_NONE; 883 return IRQ_NONE;
884
999 dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc); 885 dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc);
1000 886
1001 if(!shpchp_poll_mode) { 887 if(!shpchp_poll_mode) {
1002 /* Mask Global Interrupt Mask - see implementation note on p. 139 */ 888 /*
1003 /* of SHPC spec rev 1.0*/ 889 * Mask Global Interrupt Mask - see implementation
1004 temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); 890 * note on p. 139 of SHPC spec rev 1.0
1005 temp_dword |= 0x00000001; 891 */
1006 writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); 892 serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
893 serr_int |= GLOBAL_INTR_MASK;
894 serr_int &= ~SERR_INTR_RSVDZ_MASK;
895 shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
1007 896
1008 intr_loc2 = readl(php_ctlr->creg + INTR_LOC); 897 intr_loc2 = shpc_readl(ctrl, INTR_LOC);
1009 dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); 898 dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2);
1010 } 899 }
1011 900
1012 if (intr_loc & 0x0001) { 901 if (intr_loc & CMD_INTR_PENDING) {
1013 /* 902 /*
1014 * Command Complete Interrupt Pending 903 * Command Complete Interrupt Pending
1015 * RO only - clear by writing 1 to the Command Completion 904 * RO only - clear by writing 1 to the Command Completion
1016 * Detect bit in Controller SERR-INT register 905 * Detect bit in Controller SERR-INT register
1017 */ 906 */
1018 temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); 907 serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
1019 temp_dword &= 0xfffdffff; 908 serr_int &= ~SERR_INTR_RSVDZ_MASK;
1020 writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); 909 shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
910
1021 ctrl->cmd_busy = 0; 911 ctrl->cmd_busy = 0;
1022 wake_up_interruptible(&ctrl->queue); 912 wake_up_interruptible(&ctrl->queue);
1023 } 913 }
1024 914
1025 if ((intr_loc = (intr_loc >> 1)) == 0) 915 if (!(intr_loc & ~CMD_INTR_PENDING))
1026 goto out; 916 goto out;
1027 917
1028 for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { 918 for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) {
1029 /* To find out which slot has interrupt pending */ 919 /* To find out which slot has interrupt pending */
1030 if ((intr_loc >> hp_slot) & 0x01) { 920 if (!(intr_loc & SLOT_INTR_PENDING(hp_slot)))
1031 temp_dword = readl(php_ctlr->creg + SLOT1 + (4*hp_slot)); 921 continue;
1032 dbg("%s: Slot %x with intr, slot register = %x\n", 922
1033 __FUNCTION__, hp_slot, temp_dword); 923 slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
1034 temp_byte = (temp_dword >> 16) & 0xFF; 924 dbg("%s: Slot %x with intr, slot register = %x\n",
1035 if ((php_ctlr->switch_change_callback) && (temp_byte & 0x08)) 925 __FUNCTION__, hp_slot, slot_reg);
1036 schedule_flag += php_ctlr->switch_change_callback( 926
1037 hp_slot, php_ctlr->callback_instance_id); 927 if (slot_reg & MRL_CHANGE_DETECTED)
1038 if ((php_ctlr->attention_button_callback) && (temp_byte & 0x04)) 928 php_ctlr->switch_change_callback(
1039 schedule_flag += php_ctlr->attention_button_callback( 929 hp_slot, php_ctlr->callback_instance_id);
1040 hp_slot, php_ctlr->callback_instance_id); 930
1041 if ((php_ctlr->presence_change_callback) && (temp_byte & 0x01)) 931 if (slot_reg & BUTTON_PRESS_DETECTED)
1042 schedule_flag += php_ctlr->presence_change_callback( 932 php_ctlr->attention_button_callback(
1043 hp_slot , php_ctlr->callback_instance_id); 933 hp_slot, php_ctlr->callback_instance_id);
1044 if ((php_ctlr->power_fault_callback) && (temp_byte & 0x12)) 934
1045 schedule_flag += php_ctlr->power_fault_callback( 935 if (slot_reg & PRSNT_CHANGE_DETECTED)
1046 hp_slot, php_ctlr->callback_instance_id); 936 php_ctlr->presence_change_callback(
1047 937 hp_slot , php_ctlr->callback_instance_id);
1048 /* Clear all slot events */ 938
1049 temp_dword = 0xe01f3fff; 939 if (slot_reg & (ISO_PFAULT_DETECTED | CON_PFAULT_DETECTED))
1050 writel(temp_dword, php_ctlr->creg + SLOT1 + (4*hp_slot)); 940 php_ctlr->power_fault_callback(
1051 941 hp_slot, php_ctlr->callback_instance_id);
1052 intr_loc2 = readl(php_ctlr->creg + INTR_LOC); 942
1053 dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); 943 /* Clear all slot events */
1054 } 944 slot_reg &= ~SLOT_REG_RSVDZ_MASK;
945 shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg);
1055 } 946 }
1056 out: 947 out:
1057 if (!shpchp_poll_mode) { 948 if (!shpchp_poll_mode) {
1058 /* Unmask Global Interrupt Mask */ 949 /* Unmask Global Interrupt Mask */
1059 temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); 950 serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
1060 temp_dword &= 0xfffffffe; 951 serr_int &= ~(GLOBAL_INTR_MASK | SERR_INTR_RSVDZ_MASK);
1061 writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); 952 shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
1062 } 953 }
1063 954
1064 return IRQ_HANDLED; 955 return IRQ_HANDLED;
@@ -1067,11 +958,11 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
1067static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) 958static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
1068{ 959{
1069 int retval = 0; 960 int retval = 0;
1070 struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; 961 struct controller *ctrl = slot->ctrl;
1071 enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; 962 enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
1072 u8 pi = readb(php_ctlr->creg + PROG_INTERFACE); 963 u8 pi = shpc_readb(ctrl, PROG_INTERFACE);
1073 u32 slot_avail1 = readl(php_ctlr->creg + SLOT_AVAIL1); 964 u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1);
1074 u32 slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2); 965 u32 slot_avail2 = shpc_readl(ctrl, SLOT_AVAIL2);
1075 966
1076 DBG_ENTER_ROUTINE 967 DBG_ENTER_ROUTINE
1077 968
@@ -1114,10 +1005,10 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
1114static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value) 1005static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value)
1115{ 1006{
1116 int retval = 0; 1007 int retval = 0;
1117 struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle; 1008 struct controller *ctrl = slot->ctrl;
1118 enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; 1009 enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
1119 u16 sec_bus_reg = readw(php_ctlr->creg + SEC_BUS_CONFIG); 1010 u16 sec_bus_reg = shpc_readw(ctrl, SEC_BUS_CONFIG);
1120 u8 pi = readb(php_ctlr->creg + PROG_INTERFACE); 1011 u8 pi = shpc_readb(ctrl, PROG_INTERFACE);
1121 u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7); 1012 u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7);
1122 1013
1123 DBG_ENTER_ROUTINE 1014 DBG_ENTER_ROUTINE
@@ -1206,28 +1097,14 @@ static struct hpc_ops shpchp_hpc_ops = {
1206 .release_ctlr = hpc_release_ctlr, 1097 .release_ctlr = hpc_release_ctlr,
1207}; 1098};
1208 1099
1209inline static int shpc_indirect_creg_read(struct controller *ctrl, int index,
1210 u32 *value)
1211{
1212 int rc;
1213 u32 cap_offset = ctrl->cap_offset;
1214 struct pci_dev *pdev = ctrl->pci_dev;
1215
1216 rc = pci_write_config_byte(pdev, cap_offset + DWORD_SELECT, index);
1217 if (rc)
1218 return rc;
1219 return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value);
1220}
1221
1222int shpc_init(struct controller * ctrl, struct pci_dev * pdev) 1100int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
1223{ 1101{
1224 struct php_ctlr_state_s *php_ctlr, *p; 1102 struct php_ctlr_state_s *php_ctlr, *p;
1225 void *instance_id = ctrl; 1103 void *instance_id = ctrl;
1226 int rc, num_slots = 0; 1104 int rc, num_slots = 0;
1227 u8 hp_slot; 1105 u8 hp_slot;
1228 static int first = 1;
1229 u32 shpc_base_offset; 1106 u32 shpc_base_offset;
1230 u32 tempdword, slot_reg; 1107 u32 tempdword, slot_reg, slot_config;
1231 u8 i; 1108 u8 i;
1232 1109
1233 DBG_ENTER_ROUTINE 1110 DBG_ENTER_ROUTINE
@@ -1257,13 +1134,13 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
1257 } 1134 }
1258 dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset); 1135 dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset);
1259 1136
1260 rc = shpc_indirect_creg_read(ctrl, 0, &shpc_base_offset); 1137 rc = shpc_indirect_read(ctrl, 0, &shpc_base_offset);
1261 if (rc) { 1138 if (rc) {
1262 err("%s: cannot read base_offset\n", __FUNCTION__); 1139 err("%s: cannot read base_offset\n", __FUNCTION__);
1263 goto abort_free_ctlr; 1140 goto abort_free_ctlr;
1264 } 1141 }
1265 1142
1266 rc = shpc_indirect_creg_read(ctrl, 3, &tempdword); 1143 rc = shpc_indirect_read(ctrl, 3, &tempdword);
1267 if (rc) { 1144 if (rc) {
1268 err("%s: cannot read slot config\n", __FUNCTION__); 1145 err("%s: cannot read slot config\n", __FUNCTION__);
1269 goto abort_free_ctlr; 1146 goto abort_free_ctlr;
@@ -1272,7 +1149,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
1272 dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots); 1149 dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots);
1273 1150
1274 for (i = 0; i < 9 + num_slots; i++) { 1151 for (i = 0; i < 9 + num_slots; i++) {
1275 rc = shpc_indirect_creg_read(ctrl, i, &tempdword); 1152 rc = shpc_indirect_read(ctrl, i, &tempdword);
1276 if (rc) { 1153 if (rc) {
1277 err("%s: cannot read creg (index = %d)\n", 1154 err("%s: cannot read creg (index = %d)\n",
1278 __FUNCTION__, i); 1155 __FUNCTION__, i);
@@ -1287,11 +1164,6 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
1287 ctrl->mmio_size = 0x24 + 0x4 * num_slots; 1164 ctrl->mmio_size = 0x24 + 0x4 * num_slots;
1288 } 1165 }
1289 1166
1290 if (first) {
1291 spin_lock_init(&hpc_event_lock);
1292 first = 0;
1293 }
1294
1295 info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, 1167 info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor,
1296 pdev->subsystem_device); 1168 pdev->subsystem_device);
1297 1169
@@ -1326,29 +1198,39 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
1326 php_ctlr->power_fault_callback = shpchp_handle_power_fault; 1198 php_ctlr->power_fault_callback = shpchp_handle_power_fault;
1327 php_ctlr->callback_instance_id = instance_id; 1199 php_ctlr->callback_instance_id = instance_id;
1328 1200
1201 ctrl->hpc_ctlr_handle = php_ctlr;
1202 ctrl->hpc_ops = &shpchp_hpc_ops;
1203
1329 /* Return PCI Controller Info */ 1204 /* Return PCI Controller Info */
1330 php_ctlr->slot_device_offset = (readl(php_ctlr->creg + SLOT_CONFIG) & FIRST_DEV_NUM ) >> 8; 1205 slot_config = shpc_readl(ctrl, SLOT_CONFIG);
1331 php_ctlr->num_slots = readl(php_ctlr->creg + SLOT_CONFIG) & SLOT_NUM; 1206 php_ctlr->slot_device_offset = (slot_config & FIRST_DEV_NUM) >> 8;
1207 php_ctlr->num_slots = slot_config & SLOT_NUM;
1332 dbg("%s: slot_device_offset %x\n", __FUNCTION__, php_ctlr->slot_device_offset); 1208 dbg("%s: slot_device_offset %x\n", __FUNCTION__, php_ctlr->slot_device_offset);
1333 dbg("%s: num_slots %x\n", __FUNCTION__, php_ctlr->num_slots); 1209 dbg("%s: num_slots %x\n", __FUNCTION__, php_ctlr->num_slots);
1334 1210
1335 /* Mask Global Interrupt Mask & Command Complete Interrupt Mask */ 1211 /* Mask Global Interrupt Mask & Command Complete Interrupt Mask */
1336 tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE); 1212 tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
1337 dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); 1213 dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
1338 tempdword = 0x0003000f; 1214 tempdword |= (GLOBAL_INTR_MASK | GLOBAL_SERR_MASK |
1339 writel(tempdword, php_ctlr->creg + SERR_INTR_ENABLE); 1215 COMMAND_INTR_MASK | ARBITER_SERR_MASK);
1340 tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE); 1216 tempdword &= ~SERR_INTR_RSVDZ_MASK;
1217 shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword);
1218 tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
1341 dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); 1219 dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
1342 1220
1343 /* Mask the MRL sensor SERR Mask of individual slot in 1221 /* Mask the MRL sensor SERR Mask of individual slot in
1344 * Slot SERR-INT Mask & clear all the existing event if any 1222 * Slot SERR-INT Mask & clear all the existing event if any
1345 */ 1223 */
1346 for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { 1224 for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) {
1347 slot_reg = readl(php_ctlr->creg + SLOT1 + 4*hp_slot ); 1225 slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
1348 dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, 1226 dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__,
1349 hp_slot, slot_reg); 1227 hp_slot, slot_reg);
1350 tempdword = 0xffff3fff; 1228 slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
1351 writel(tempdword, php_ctlr->creg + SLOT1 + (4*hp_slot)); 1229 BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
1230 CON_PFAULT_INTR_MASK | MRL_CHANGE_SERR_MASK |
1231 CON_PFAULT_SERR_MASK);
1232 slot_reg &= ~SLOT_REG_RSVDZ_MASK;
1233 shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg);
1352 } 1234 }
1353 1235
1354 if (shpchp_poll_mode) {/* Install interrupt polling code */ 1236 if (shpchp_poll_mode) {/* Install interrupt polling code */
@@ -1392,24 +1274,37 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
1392 } 1274 }
1393 spin_unlock(&list_lock); 1275 spin_unlock(&list_lock);
1394 1276
1395
1396 ctlr_seq_num++; 1277 ctlr_seq_num++;
1397 ctrl->hpc_ctlr_handle = php_ctlr;
1398 ctrl->hpc_ops = &shpchp_hpc_ops;
1399 1278
1279 /*
1280 * If this is the first controller to be initialized,
1281 * initialize the shpchpd work queue
1282 */
1283 if (atomic_add_return(1, &shpchp_num_controllers) == 1) {
1284 shpchp_wq = create_singlethread_workqueue("shpchpd");
1285 if (!shpchp_wq)
1286 return -ENOMEM;
1287 }
1288
1289 /*
1290 * Unmask all event interrupts of all slots
1291 */
1400 for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { 1292 for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) {
1401 slot_reg = readl(php_ctlr->creg + SLOT1 + 4*hp_slot ); 1293 slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
1402 dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, 1294 dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__,
1403 hp_slot, slot_reg); 1295 hp_slot, slot_reg);
1404 tempdword = 0xe01f3fff; 1296 slot_reg &= ~(PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
1405 writel(tempdword, php_ctlr->creg + SLOT1 + (4*hp_slot)); 1297 BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
1298 CON_PFAULT_INTR_MASK | SLOT_REG_RSVDZ_MASK);
1299 shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg);
1406 } 1300 }
1407 if (!shpchp_poll_mode) { 1301 if (!shpchp_poll_mode) {
1408 /* Unmask all general input interrupts and SERR */ 1302 /* Unmask all general input interrupts and SERR */
1409 tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE); 1303 tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
1410 tempdword = 0x0000000a; 1304 tempdword &= ~(GLOBAL_INTR_MASK | COMMAND_INTR_MASK |
1411 writel(tempdword, php_ctlr->creg + SERR_INTR_ENABLE); 1305 SERR_INTR_RSVDZ_MASK);
1412 tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE); 1306 shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword);
1307 tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
1413 dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); 1308 dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
1414 } 1309 }
1415 1310