1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * IBM Hot Plug Controller Driver |
4 | * |
5 | * Written By: Jyoti Shah, IBM Corporation |
6 | * |
7 | * Copyright (C) 2001-2003 IBM Corp. |
8 | * |
9 | * All rights reserved. |
10 | * |
11 | * Send feedback to <gregkh@us.ibm.com> |
12 | * <jshah@us.ibm.com> |
13 | * |
14 | */ |
15 | |
16 | #include <linux/wait.h> |
17 | #include <linux/time.h> |
18 | #include <linux/completion.h> |
19 | #include <linux/delay.h> |
20 | #include <linux/module.h> |
21 | #include <linux/pci.h> |
22 | #include <linux/init.h> |
23 | #include <linux/mutex.h> |
24 | #include <linux/sched.h> |
25 | #include <linux/kthread.h> |
26 | #include "ibmphp.h" |
27 | |
28 | static int to_debug = 0; |
29 | #define debug_polling(fmt, arg...) do { if (to_debug) debug(fmt, arg); } while (0) |
30 | |
31 | //---------------------------------------------------------------------------- |
32 | // timeout values |
33 | //---------------------------------------------------------------------------- |
34 | #define CMD_COMPLETE_TOUT_SEC 60 // give HPC 60 sec to finish cmd |
35 | #define HPC_CTLR_WORKING_TOUT 60 // give HPC 60 sec to finish cmd |
36 | #define HPC_GETACCESS_TIMEOUT 60 // seconds |
37 | #define POLL_INTERVAL_SEC 2 // poll HPC every 2 seconds |
38 | #define POLL_LATCH_CNT 5 // poll latch 5 times, then poll slots |
39 | |
40 | //---------------------------------------------------------------------------- |
41 | // Winnipeg Architected Register Offsets |
42 | //---------------------------------------------------------------------------- |
43 | #define WPG_I2CMBUFL_OFFSET 0x08 // I2C Message Buffer Low |
44 | #define WPG_I2CMOSUP_OFFSET 0x10 // I2C Master Operation Setup Reg |
45 | #define WPG_I2CMCNTL_OFFSET 0x20 // I2C Master Control Register |
46 | #define WPG_I2CPARM_OFFSET 0x40 // I2C Parameter Register |
47 | #define WPG_I2CSTAT_OFFSET 0x70 // I2C Status Register |
48 | |
49 | //---------------------------------------------------------------------------- |
50 | // Winnipeg Store Type commands (Add this commands to the register offset) |
51 | //---------------------------------------------------------------------------- |
52 | #define WPG_I2C_AND 0x1000 // I2C AND operation |
53 | #define WPG_I2C_OR 0x2000 // I2C OR operation |
54 | |
55 | //---------------------------------------------------------------------------- |
56 | // Command set for I2C Master Operation Setup Register |
57 | //---------------------------------------------------------------------------- |
58 | #define WPG_READATADDR_MASK 0x00010000 // read,bytes,I2C shifted,index |
59 | #define WPG_WRITEATADDR_MASK 0x40010000 // write,bytes,I2C shifted,index |
60 | #define WPG_READDIRECT_MASK 0x10010000 |
61 | #define WPG_WRITEDIRECT_MASK 0x60010000 |
62 | |
63 | |
64 | //---------------------------------------------------------------------------- |
65 | // bit masks for I2C Master Control Register |
66 | //---------------------------------------------------------------------------- |
67 | #define WPG_I2CMCNTL_STARTOP_MASK 0x00000002 // Start the Operation |
68 | |
69 | //---------------------------------------------------------------------------- |
70 | // |
71 | //---------------------------------------------------------------------------- |
72 | #define WPG_I2C_IOREMAP_SIZE 0x2044 // size of linear address interval |
73 | |
74 | //---------------------------------------------------------------------------- |
75 | // command index |
76 | //---------------------------------------------------------------------------- |
77 | #define WPG_1ST_SLOT_INDEX 0x01 // index - 1st slot for ctlr |
78 | #define WPG_CTLR_INDEX 0x0F // index - ctlr |
79 | #define WPG_1ST_EXTSLOT_INDEX 0x10 // index - 1st ext slot for ctlr |
80 | #define WPG_1ST_BUS_INDEX 0x1F // index - 1st bus for ctlr |
81 | |
82 | //---------------------------------------------------------------------------- |
83 | // macro utilities |
84 | //---------------------------------------------------------------------------- |
85 | // if bits 20,22,25,26,27,29,30 are OFF return 1 |
86 | #define HPC_I2CSTATUS_CHECK(s) ((u8)((s & 0x00000A76) ? 0 : 1)) |
87 | |
88 | //---------------------------------------------------------------------------- |
89 | // global variables |
90 | //---------------------------------------------------------------------------- |
91 | static DEFINE_MUTEX(sem_hpcaccess); // lock access to HPC |
92 | static DEFINE_MUTEX(operations_mutex); // lock all operations and |
93 | // access to data structures |
94 | static DECLARE_COMPLETION(exit_complete); // make sure polling thread goes away |
95 | static struct task_struct *ibmphp_poll_thread; |
96 | //---------------------------------------------------------------------------- |
97 | // local function prototypes |
98 | //---------------------------------------------------------------------------- |
99 | static u8 i2c_ctrl_read(struct controller *, void __iomem *, u8); |
100 | static u8 i2c_ctrl_write(struct controller *, void __iomem *, u8, u8); |
101 | static u8 hpc_writecmdtoindex(u8, u8); |
102 | static u8 hpc_readcmdtoindex(u8, u8); |
103 | static void get_hpc_access(void); |
104 | static void free_hpc_access(void); |
105 | static int poll_hpc(void *data); |
106 | static int process_changeinstatus(struct slot *, struct slot *); |
107 | static int process_changeinlatch(u8, u8, struct controller *); |
108 | static int hpc_wait_ctlr_notworking(int, struct controller *, void __iomem *, u8 *); |
109 | //---------------------------------------------------------------------------- |
110 | |
111 | |
112 | /*---------------------------------------------------------------------- |
113 | * Name: i2c_ctrl_read |
114 | * |
115 | * Action: read from HPC over I2C |
116 | * |
117 | *---------------------------------------------------------------------*/ |
118 | static u8 i2c_ctrl_read(struct controller *ctlr_ptr, void __iomem *WPGBbar, u8 index) |
119 | { |
120 | u8 status; |
121 | int i; |
122 | void __iomem *wpg_addr; // base addr + offset |
123 | unsigned long wpg_data; // data to/from WPG LOHI format |
124 | unsigned long ultemp; |
125 | unsigned long data; // actual data HILO format |
126 | |
127 | debug_polling("%s - Entry WPGBbar[%p] index[%x] \n" , __func__, WPGBbar, index); |
128 | |
129 | //-------------------------------------------------------------------- |
130 | // READ - step 1 |
131 | // read at address, byte length, I2C address (shifted), index |
132 | // or read direct, byte length, index |
133 | if (ctlr_ptr->ctlr_type == 0x02) { |
134 | data = WPG_READATADDR_MASK; |
135 | // fill in I2C address |
136 | ultemp = (unsigned long)ctlr_ptr->u.wpeg_ctlr.i2c_addr; |
137 | ultemp = ultemp >> 1; |
138 | data |= (ultemp << 8); |
139 | |
140 | // fill in index |
141 | data |= (unsigned long)index; |
142 | } else if (ctlr_ptr->ctlr_type == 0x04) { |
143 | data = WPG_READDIRECT_MASK; |
144 | |
145 | // fill in index |
146 | ultemp = (unsigned long)index; |
147 | ultemp = ultemp << 8; |
148 | data |= ultemp; |
149 | } else { |
150 | err("this controller type is not supported \n" ); |
151 | return HPC_ERROR; |
152 | } |
153 | |
154 | wpg_data = swab32(data); // swap data before writing |
155 | wpg_addr = WPGBbar + WPG_I2CMOSUP_OFFSET; |
156 | writel(val: wpg_data, addr: wpg_addr); |
157 | |
158 | //-------------------------------------------------------------------- |
159 | // READ - step 2 : clear the message buffer |
160 | data = 0x00000000; |
161 | wpg_data = swab32(data); |
162 | wpg_addr = WPGBbar + WPG_I2CMBUFL_OFFSET; |
163 | writel(val: wpg_data, addr: wpg_addr); |
164 | |
165 | //-------------------------------------------------------------------- |
166 | // READ - step 3 : issue start operation, I2C master control bit 30:ON |
167 | // 2020 : [20] OR operation at [20] offset 0x20 |
168 | data = WPG_I2CMCNTL_STARTOP_MASK; |
169 | wpg_data = swab32(data); |
170 | wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET + WPG_I2C_OR; |
171 | writel(val: wpg_data, addr: wpg_addr); |
172 | |
173 | //-------------------------------------------------------------------- |
174 | // READ - step 4 : wait until start operation bit clears |
175 | i = CMD_COMPLETE_TOUT_SEC; |
176 | while (i) { |
177 | msleep(msecs: 10); |
178 | wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET; |
179 | wpg_data = readl(addr: wpg_addr); |
180 | data = swab32(wpg_data); |
181 | if (!(data & WPG_I2CMCNTL_STARTOP_MASK)) |
182 | break; |
183 | i--; |
184 | } |
185 | if (i == 0) { |
186 | debug("%s - Error : WPG timeout\n" , __func__); |
187 | return HPC_ERROR; |
188 | } |
189 | //-------------------------------------------------------------------- |
190 | // READ - step 5 : read I2C status register |
191 | i = CMD_COMPLETE_TOUT_SEC; |
192 | while (i) { |
193 | msleep(msecs: 10); |
194 | wpg_addr = WPGBbar + WPG_I2CSTAT_OFFSET; |
195 | wpg_data = readl(addr: wpg_addr); |
196 | data = swab32(wpg_data); |
197 | if (HPC_I2CSTATUS_CHECK(data)) |
198 | break; |
199 | i--; |
200 | } |
201 | if (i == 0) { |
202 | debug("ctrl_read - Exit Error:I2C timeout\n" ); |
203 | return HPC_ERROR; |
204 | } |
205 | |
206 | //-------------------------------------------------------------------- |
207 | // READ - step 6 : get DATA |
208 | wpg_addr = WPGBbar + WPG_I2CMBUFL_OFFSET; |
209 | wpg_data = readl(addr: wpg_addr); |
210 | data = swab32(wpg_data); |
211 | |
212 | status = (u8) data; |
213 | |
214 | debug_polling("%s - Exit index[%x] status[%x]\n" , __func__, index, status); |
215 | |
216 | return (status); |
217 | } |
218 | |
219 | /*---------------------------------------------------------------------- |
220 | * Name: i2c_ctrl_write |
221 | * |
222 | * Action: write to HPC over I2C |
223 | * |
224 | * Return 0 or error codes |
225 | *---------------------------------------------------------------------*/ |
226 | static u8 i2c_ctrl_write(struct controller *ctlr_ptr, void __iomem *WPGBbar, u8 index, u8 cmd) |
227 | { |
228 | u8 rc; |
229 | void __iomem *wpg_addr; // base addr + offset |
230 | unsigned long wpg_data; // data to/from WPG LOHI format |
231 | unsigned long ultemp; |
232 | unsigned long data; // actual data HILO format |
233 | int i; |
234 | |
235 | debug_polling("%s - Entry WPGBbar[%p] index[%x] cmd[%x]\n" , __func__, WPGBbar, index, cmd); |
236 | |
237 | rc = 0; |
238 | //-------------------------------------------------------------------- |
239 | // WRITE - step 1 |
240 | // write at address, byte length, I2C address (shifted), index |
241 | // or write direct, byte length, index |
242 | data = 0x00000000; |
243 | |
244 | if (ctlr_ptr->ctlr_type == 0x02) { |
245 | data = WPG_WRITEATADDR_MASK; |
246 | // fill in I2C address |
247 | ultemp = (unsigned long)ctlr_ptr->u.wpeg_ctlr.i2c_addr; |
248 | ultemp = ultemp >> 1; |
249 | data |= (ultemp << 8); |
250 | |
251 | // fill in index |
252 | data |= (unsigned long)index; |
253 | } else if (ctlr_ptr->ctlr_type == 0x04) { |
254 | data = WPG_WRITEDIRECT_MASK; |
255 | |
256 | // fill in index |
257 | ultemp = (unsigned long)index; |
258 | ultemp = ultemp << 8; |
259 | data |= ultemp; |
260 | } else { |
261 | err("this controller type is not supported \n" ); |
262 | return HPC_ERROR; |
263 | } |
264 | |
265 | wpg_data = swab32(data); // swap data before writing |
266 | wpg_addr = WPGBbar + WPG_I2CMOSUP_OFFSET; |
267 | writel(val: wpg_data, addr: wpg_addr); |
268 | |
269 | //-------------------------------------------------------------------- |
270 | // WRITE - step 2 : clear the message buffer |
271 | data = 0x00000000 | (unsigned long)cmd; |
272 | wpg_data = swab32(data); |
273 | wpg_addr = WPGBbar + WPG_I2CMBUFL_OFFSET; |
274 | writel(val: wpg_data, addr: wpg_addr); |
275 | |
276 | //-------------------------------------------------------------------- |
277 | // WRITE - step 3 : issue start operation,I2C master control bit 30:ON |
278 | // 2020 : [20] OR operation at [20] offset 0x20 |
279 | data = WPG_I2CMCNTL_STARTOP_MASK; |
280 | wpg_data = swab32(data); |
281 | wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET + WPG_I2C_OR; |
282 | writel(val: wpg_data, addr: wpg_addr); |
283 | |
284 | //-------------------------------------------------------------------- |
285 | // WRITE - step 4 : wait until start operation bit clears |
286 | i = CMD_COMPLETE_TOUT_SEC; |
287 | while (i) { |
288 | msleep(msecs: 10); |
289 | wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET; |
290 | wpg_data = readl(addr: wpg_addr); |
291 | data = swab32(wpg_data); |
292 | if (!(data & WPG_I2CMCNTL_STARTOP_MASK)) |
293 | break; |
294 | i--; |
295 | } |
296 | if (i == 0) { |
297 | debug("%s - Exit Error:WPG timeout\n" , __func__); |
298 | rc = HPC_ERROR; |
299 | } |
300 | |
301 | //-------------------------------------------------------------------- |
302 | // WRITE - step 5 : read I2C status register |
303 | i = CMD_COMPLETE_TOUT_SEC; |
304 | while (i) { |
305 | msleep(msecs: 10); |
306 | wpg_addr = WPGBbar + WPG_I2CSTAT_OFFSET; |
307 | wpg_data = readl(addr: wpg_addr); |
308 | data = swab32(wpg_data); |
309 | if (HPC_I2CSTATUS_CHECK(data)) |
310 | break; |
311 | i--; |
312 | } |
313 | if (i == 0) { |
314 | debug("ctrl_read - Error : I2C timeout\n" ); |
315 | rc = HPC_ERROR; |
316 | } |
317 | |
318 | debug_polling("%s Exit rc[%x]\n" , __func__, rc); |
319 | return (rc); |
320 | } |
321 | |
322 | //------------------------------------------------------------ |
323 | // Read from ISA type HPC |
324 | //------------------------------------------------------------ |
325 | static u8 isa_ctrl_read(struct controller *ctlr_ptr, u8 offset) |
326 | { |
327 | u16 start_address; |
328 | u8 data; |
329 | |
330 | start_address = ctlr_ptr->u.isa_ctlr.io_start; |
331 | data = inb(port: start_address + offset); |
332 | return data; |
333 | } |
334 | |
335 | //-------------------------------------------------------------- |
336 | // Write to ISA type HPC |
337 | //-------------------------------------------------------------- |
338 | static void isa_ctrl_write(struct controller *ctlr_ptr, u8 offset, u8 data) |
339 | { |
340 | u16 start_address; |
341 | u16 port_address; |
342 | |
343 | start_address = ctlr_ptr->u.isa_ctlr.io_start; |
344 | port_address = start_address + (u16) offset; |
345 | outb(value: data, port: port_address); |
346 | } |
347 | |
348 | static u8 pci_ctrl_read(struct controller *ctrl, u8 offset) |
349 | { |
350 | u8 data = 0x00; |
351 | debug("inside pci_ctrl_read\n" ); |
352 | if (ctrl->ctrl_dev) |
353 | pci_read_config_byte(dev: ctrl->ctrl_dev, HPC_PCI_OFFSET + offset, val: &data); |
354 | return data; |
355 | } |
356 | |
357 | static u8 pci_ctrl_write(struct controller *ctrl, u8 offset, u8 data) |
358 | { |
359 | u8 rc = -ENODEV; |
360 | debug("inside pci_ctrl_write\n" ); |
361 | if (ctrl->ctrl_dev) { |
362 | pci_write_config_byte(dev: ctrl->ctrl_dev, HPC_PCI_OFFSET + offset, val: data); |
363 | rc = 0; |
364 | } |
365 | return rc; |
366 | } |
367 | |
368 | static u8 ctrl_read(struct controller *ctlr, void __iomem *base, u8 offset) |
369 | { |
370 | u8 rc; |
371 | switch (ctlr->ctlr_type) { |
372 | case 0: |
373 | rc = isa_ctrl_read(ctlr_ptr: ctlr, offset); |
374 | break; |
375 | case 1: |
376 | rc = pci_ctrl_read(ctrl: ctlr, offset); |
377 | break; |
378 | case 2: |
379 | case 4: |
380 | rc = i2c_ctrl_read(ctlr_ptr: ctlr, WPGBbar: base, index: offset); |
381 | break; |
382 | default: |
383 | return -ENODEV; |
384 | } |
385 | return rc; |
386 | } |
387 | |
388 | static u8 ctrl_write(struct controller *ctlr, void __iomem *base, u8 offset, u8 data) |
389 | { |
390 | u8 rc = 0; |
391 | switch (ctlr->ctlr_type) { |
392 | case 0: |
393 | isa_ctrl_write(ctlr_ptr: ctlr, offset, data); |
394 | break; |
395 | case 1: |
396 | rc = pci_ctrl_write(ctrl: ctlr, offset, data); |
397 | break; |
398 | case 2: |
399 | case 4: |
400 | rc = i2c_ctrl_write(ctlr_ptr: ctlr, WPGBbar: base, index: offset, cmd: data); |
401 | break; |
402 | default: |
403 | return -ENODEV; |
404 | } |
405 | return rc; |
406 | } |
407 | /*---------------------------------------------------------------------- |
408 | * Name: hpc_writecmdtoindex() |
409 | * |
410 | * Action: convert a write command to proper index within a controller |
411 | * |
412 | * Return index, HPC_ERROR |
413 | *---------------------------------------------------------------------*/ |
414 | static u8 hpc_writecmdtoindex(u8 cmd, u8 index) |
415 | { |
416 | u8 rc; |
417 | |
418 | switch (cmd) { |
419 | case HPC_CTLR_ENABLEIRQ: // 0x00.N.15 |
420 | case HPC_CTLR_CLEARIRQ: // 0x06.N.15 |
421 | case HPC_CTLR_RESET: // 0x07.N.15 |
422 | case HPC_CTLR_IRQSTEER: // 0x08.N.15 |
423 | case HPC_CTLR_DISABLEIRQ: // 0x01.N.15 |
424 | case HPC_ALLSLOT_ON: // 0x11.N.15 |
425 | case HPC_ALLSLOT_OFF: // 0x12.N.15 |
426 | rc = 0x0F; |
427 | break; |
428 | |
429 | case HPC_SLOT_OFF: // 0x02.Y.0-14 |
430 | case HPC_SLOT_ON: // 0x03.Y.0-14 |
431 | case HPC_SLOT_ATTNOFF: // 0x04.N.0-14 |
432 | case HPC_SLOT_ATTNON: // 0x05.N.0-14 |
433 | case HPC_SLOT_BLINKLED: // 0x13.N.0-14 |
434 | rc = index; |
435 | break; |
436 | |
437 | case HPC_BUS_33CONVMODE: |
438 | case HPC_BUS_66CONVMODE: |
439 | case HPC_BUS_66PCIXMODE: |
440 | case HPC_BUS_100PCIXMODE: |
441 | case HPC_BUS_133PCIXMODE: |
442 | rc = index + WPG_1ST_BUS_INDEX - 1; |
443 | break; |
444 | |
445 | default: |
446 | err("hpc_writecmdtoindex - Error invalid cmd[%x]\n" , cmd); |
447 | rc = HPC_ERROR; |
448 | } |
449 | |
450 | return rc; |
451 | } |
452 | |
453 | /*---------------------------------------------------------------------- |
454 | * Name: hpc_readcmdtoindex() |
455 | * |
456 | * Action: convert a read command to proper index within a controller |
457 | * |
458 | * Return index, HPC_ERROR |
459 | *---------------------------------------------------------------------*/ |
460 | static u8 hpc_readcmdtoindex(u8 cmd, u8 index) |
461 | { |
462 | u8 rc; |
463 | |
464 | switch (cmd) { |
465 | case READ_CTLRSTATUS: |
466 | rc = 0x0F; |
467 | break; |
468 | case READ_SLOTSTATUS: |
469 | case READ_ALLSTAT: |
470 | rc = index; |
471 | break; |
472 | case READ_EXTSLOTSTATUS: |
473 | rc = index + WPG_1ST_EXTSLOT_INDEX; |
474 | break; |
475 | case READ_BUSSTATUS: |
476 | rc = index + WPG_1ST_BUS_INDEX - 1; |
477 | break; |
478 | case READ_SLOTLATCHLOWREG: |
479 | rc = 0x28; |
480 | break; |
481 | case READ_REVLEVEL: |
482 | rc = 0x25; |
483 | break; |
484 | case READ_HPCOPTIONS: |
485 | rc = 0x27; |
486 | break; |
487 | default: |
488 | rc = HPC_ERROR; |
489 | } |
490 | return rc; |
491 | } |
492 | |
493 | /*---------------------------------------------------------------------- |
494 | * Name: HPCreadslot() |
495 | * |
496 | * Action: issue a READ command to HPC |
497 | * |
498 | * Input: pslot - cannot be NULL for READ_ALLSTAT |
499 | * pstatus - can be NULL for READ_ALLSTAT |
500 | * |
501 | * Return 0 or error codes |
502 | *---------------------------------------------------------------------*/ |
503 | int ibmphp_hpc_readslot(struct slot *pslot, u8 cmd, u8 *pstatus) |
504 | { |
505 | void __iomem *wpg_bbar = NULL; |
506 | struct controller *ctlr_ptr; |
507 | u8 index, status; |
508 | int rc = 0; |
509 | int busindex; |
510 | |
511 | debug_polling("%s - Entry pslot[%p] cmd[%x] pstatus[%p]\n" , __func__, pslot, cmd, pstatus); |
512 | |
513 | if ((pslot == NULL) |
514 | || ((pstatus == NULL) && (cmd != READ_ALLSTAT) && (cmd != READ_BUSSTATUS))) { |
515 | rc = -EINVAL; |
516 | err("%s - Error invalid pointer, rc[%d]\n" , __func__, rc); |
517 | return rc; |
518 | } |
519 | |
520 | if (cmd == READ_BUSSTATUS) { |
521 | busindex = ibmphp_get_bus_index(pslot->bus); |
522 | if (busindex < 0) { |
523 | rc = -EINVAL; |
524 | err("%s - Exit Error:invalid bus, rc[%d]\n" , __func__, rc); |
525 | return rc; |
526 | } else |
527 | index = (u8) busindex; |
528 | } else |
529 | index = pslot->ctlr_index; |
530 | |
531 | index = hpc_readcmdtoindex(cmd, index); |
532 | |
533 | if (index == HPC_ERROR) { |
534 | rc = -EINVAL; |
535 | err("%s - Exit Error:invalid index, rc[%d]\n" , __func__, rc); |
536 | return rc; |
537 | } |
538 | |
539 | ctlr_ptr = pslot->ctrl; |
540 | |
541 | get_hpc_access(); |
542 | |
543 | //-------------------------------------------------------------------- |
544 | // map physical address to logical address |
545 | //-------------------------------------------------------------------- |
546 | if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) |
547 | wpg_bbar = ioremap(offset: ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE); |
548 | |
549 | //-------------------------------------------------------------------- |
550 | // check controller status before reading |
551 | //-------------------------------------------------------------------- |
552 | rc = hpc_wait_ctlr_notworking(HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar, &status); |
553 | if (!rc) { |
554 | switch (cmd) { |
555 | case READ_ALLSTAT: |
556 | // update the slot structure |
557 | pslot->ctrl->status = status; |
558 | pslot->status = ctrl_read(ctlr: ctlr_ptr, base: wpg_bbar, offset: index); |
559 | rc = hpc_wait_ctlr_notworking(HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar, |
560 | &status); |
561 | if (!rc) |
562 | pslot->ext_status = ctrl_read(ctlr: ctlr_ptr, base: wpg_bbar, offset: index + WPG_1ST_EXTSLOT_INDEX); |
563 | |
564 | break; |
565 | |
566 | case READ_SLOTSTATUS: |
567 | // DO NOT update the slot structure |
568 | *pstatus = ctrl_read(ctlr: ctlr_ptr, base: wpg_bbar, offset: index); |
569 | break; |
570 | |
571 | case READ_EXTSLOTSTATUS: |
572 | // DO NOT update the slot structure |
573 | *pstatus = ctrl_read(ctlr: ctlr_ptr, base: wpg_bbar, offset: index); |
574 | break; |
575 | |
576 | case READ_CTLRSTATUS: |
577 | // DO NOT update the slot structure |
578 | *pstatus = status; |
579 | break; |
580 | |
581 | case READ_BUSSTATUS: |
582 | pslot->busstatus = ctrl_read(ctlr: ctlr_ptr, base: wpg_bbar, offset: index); |
583 | break; |
584 | case READ_REVLEVEL: |
585 | *pstatus = ctrl_read(ctlr: ctlr_ptr, base: wpg_bbar, offset: index); |
586 | break; |
587 | case READ_HPCOPTIONS: |
588 | *pstatus = ctrl_read(ctlr: ctlr_ptr, base: wpg_bbar, offset: index); |
589 | break; |
590 | case READ_SLOTLATCHLOWREG: |
591 | // DO NOT update the slot structure |
592 | *pstatus = ctrl_read(ctlr: ctlr_ptr, base: wpg_bbar, offset: index); |
593 | break; |
594 | |
595 | // Not used |
596 | case READ_ALLSLOT: |
597 | list_for_each_entry(pslot, &ibmphp_slot_head, |
598 | ibm_slot_list) { |
599 | index = pslot->ctlr_index; |
600 | rc = hpc_wait_ctlr_notworking(HPC_CTLR_WORKING_TOUT, ctlr_ptr, |
601 | wpg_bbar, &status); |
602 | if (!rc) { |
603 | pslot->status = ctrl_read(ctlr: ctlr_ptr, base: wpg_bbar, offset: index); |
604 | rc = hpc_wait_ctlr_notworking(HPC_CTLR_WORKING_TOUT, |
605 | ctlr_ptr, wpg_bbar, &status); |
606 | if (!rc) |
607 | pslot->ext_status = |
608 | ctrl_read(ctlr: ctlr_ptr, base: wpg_bbar, |
609 | offset: index + WPG_1ST_EXTSLOT_INDEX); |
610 | } else { |
611 | err("%s - Error ctrl_read failed\n" , __func__); |
612 | rc = -EINVAL; |
613 | break; |
614 | } |
615 | } |
616 | break; |
617 | default: |
618 | rc = -EINVAL; |
619 | break; |
620 | } |
621 | } |
622 | //-------------------------------------------------------------------- |
623 | // cleanup |
624 | //-------------------------------------------------------------------- |
625 | |
626 | // remove physical to logical address mapping |
627 | if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) |
628 | iounmap(addr: wpg_bbar); |
629 | |
630 | free_hpc_access(); |
631 | |
632 | debug_polling("%s - Exit rc[%d]\n" , __func__, rc); |
633 | return rc; |
634 | } |
635 | |
636 | /*---------------------------------------------------------------------- |
637 | * Name: ibmphp_hpc_writeslot() |
638 | * |
639 | * Action: issue a WRITE command to HPC |
640 | *---------------------------------------------------------------------*/ |
641 | int ibmphp_hpc_writeslot(struct slot *pslot, u8 cmd) |
642 | { |
643 | void __iomem *wpg_bbar = NULL; |
644 | struct controller *ctlr_ptr; |
645 | u8 index, status; |
646 | int busindex; |
647 | u8 done; |
648 | int rc = 0; |
649 | int timeout; |
650 | |
651 | debug_polling("%s - Entry pslot[%p] cmd[%x]\n" , __func__, pslot, cmd); |
652 | if (pslot == NULL) { |
653 | rc = -EINVAL; |
654 | err("%s - Error Exit rc[%d]\n" , __func__, rc); |
655 | return rc; |
656 | } |
657 | |
658 | if ((cmd == HPC_BUS_33CONVMODE) || (cmd == HPC_BUS_66CONVMODE) || |
659 | (cmd == HPC_BUS_66PCIXMODE) || (cmd == HPC_BUS_100PCIXMODE) || |
660 | (cmd == HPC_BUS_133PCIXMODE)) { |
661 | busindex = ibmphp_get_bus_index(pslot->bus); |
662 | if (busindex < 0) { |
663 | rc = -EINVAL; |
664 | err("%s - Exit Error:invalid bus, rc[%d]\n" , __func__, rc); |
665 | return rc; |
666 | } else |
667 | index = (u8) busindex; |
668 | } else |
669 | index = pslot->ctlr_index; |
670 | |
671 | index = hpc_writecmdtoindex(cmd, index); |
672 | |
673 | if (index == HPC_ERROR) { |
674 | rc = -EINVAL; |
675 | err("%s - Error Exit rc[%d]\n" , __func__, rc); |
676 | return rc; |
677 | } |
678 | |
679 | ctlr_ptr = pslot->ctrl; |
680 | |
681 | get_hpc_access(); |
682 | |
683 | //-------------------------------------------------------------------- |
684 | // map physical address to logical address |
685 | //-------------------------------------------------------------------- |
686 | if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) { |
687 | wpg_bbar = ioremap(offset: ctlr_ptr->u.wpeg_ctlr.wpegbbar, WPG_I2C_IOREMAP_SIZE); |
688 | |
689 | debug("%s - ctlr id[%x] physical[%lx] logical[%lx] i2c[%x]\n" , __func__, |
690 | ctlr_ptr->ctlr_id, (ulong) (ctlr_ptr->u.wpeg_ctlr.wpegbbar), (ulong) wpg_bbar, |
691 | ctlr_ptr->u.wpeg_ctlr.i2c_addr); |
692 | } |
693 | //-------------------------------------------------------------------- |
694 | // check controller status before writing |
695 | //-------------------------------------------------------------------- |
696 | rc = hpc_wait_ctlr_notworking(HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar, &status); |
697 | if (!rc) { |
698 | |
699 | ctrl_write(ctlr: ctlr_ptr, base: wpg_bbar, offset: index, data: cmd); |
700 | |
701 | //-------------------------------------------------------------------- |
702 | // check controller is still not working on the command |
703 | //-------------------------------------------------------------------- |
704 | timeout = CMD_COMPLETE_TOUT_SEC; |
705 | done = 0; |
706 | while (!done) { |
707 | rc = hpc_wait_ctlr_notworking(HPC_CTLR_WORKING_TOUT, ctlr_ptr, wpg_bbar, |
708 | &status); |
709 | if (!rc) { |
710 | if (NEEDTOCHECK_CMDSTATUS(cmd)) { |
711 | if (CTLR_FINISHED(status) == HPC_CTLR_FINISHED_YES) |
712 | done = 1; |
713 | } else |
714 | done = 1; |
715 | } |
716 | if (!done) { |
717 | msleep(msecs: 1000); |
718 | if (timeout < 1) { |
719 | done = 1; |
720 | err("%s - Error command complete timeout\n" , __func__); |
721 | rc = -EFAULT; |
722 | } else |
723 | timeout--; |
724 | } |
725 | } |
726 | ctlr_ptr->status = status; |
727 | } |
728 | // cleanup |
729 | |
730 | // remove physical to logical address mapping |
731 | if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4)) |
732 | iounmap(addr: wpg_bbar); |
733 | free_hpc_access(); |
734 | |
735 | debug_polling("%s - Exit rc[%d]\n" , __func__, rc); |
736 | return rc; |
737 | } |
738 | |
739 | /*---------------------------------------------------------------------- |
740 | * Name: get_hpc_access() |
741 | * |
742 | * Action: make sure only one process can access HPC at one time |
743 | *---------------------------------------------------------------------*/ |
744 | static void get_hpc_access(void) |
745 | { |
746 | mutex_lock(&sem_hpcaccess); |
747 | } |
748 | |
749 | /*---------------------------------------------------------------------- |
750 | * Name: free_hpc_access() |
751 | *---------------------------------------------------------------------*/ |
752 | void free_hpc_access(void) |
753 | { |
754 | mutex_unlock(lock: &sem_hpcaccess); |
755 | } |
756 | |
757 | /*---------------------------------------------------------------------- |
758 | * Name: ibmphp_lock_operations() |
759 | * |
760 | * Action: make sure only one process can change the data structure |
761 | *---------------------------------------------------------------------*/ |
762 | void ibmphp_lock_operations(void) |
763 | { |
764 | mutex_lock(&operations_mutex); |
765 | to_debug = 1; |
766 | } |
767 | |
768 | /*---------------------------------------------------------------------- |
769 | * Name: ibmphp_unlock_operations() |
770 | *---------------------------------------------------------------------*/ |
771 | void ibmphp_unlock_operations(void) |
772 | { |
773 | debug("%s - Entry\n" , __func__); |
774 | mutex_unlock(lock: &operations_mutex); |
775 | to_debug = 0; |
776 | debug("%s - Exit\n" , __func__); |
777 | } |
778 | |
779 | /*---------------------------------------------------------------------- |
780 | * Name: poll_hpc() |
781 | *---------------------------------------------------------------------*/ |
782 | #define POLL_LATCH_REGISTER 0 |
783 | #define POLL_SLOTS 1 |
784 | #define POLL_SLEEP 2 |
785 | static int poll_hpc(void *data) |
786 | { |
787 | struct slot myslot; |
788 | struct slot *pslot = NULL; |
789 | int rc; |
790 | int poll_state = POLL_LATCH_REGISTER; |
791 | u8 oldlatchlow = 0x00; |
792 | u8 curlatchlow = 0x00; |
793 | int poll_count = 0; |
794 | u8 ctrl_count = 0x00; |
795 | |
796 | debug("%s - Entry\n" , __func__); |
797 | |
798 | while (!kthread_should_stop()) { |
799 | /* try to get the lock to do some kind of hardware access */ |
800 | mutex_lock(&operations_mutex); |
801 | |
802 | switch (poll_state) { |
803 | case POLL_LATCH_REGISTER: |
804 | oldlatchlow = curlatchlow; |
805 | ctrl_count = 0x00; |
806 | list_for_each_entry(pslot, &ibmphp_slot_head, |
807 | ibm_slot_list) { |
808 | if (ctrl_count >= ibmphp_get_total_controllers()) |
809 | break; |
810 | if (pslot->ctrl->ctlr_relative_id == ctrl_count) { |
811 | ctrl_count++; |
812 | if (READ_SLOT_LATCH(pslot->ctrl)) { |
813 | rc = ibmphp_hpc_readslot(pslot, |
814 | READ_SLOTLATCHLOWREG, |
815 | pstatus: &curlatchlow); |
816 | if (oldlatchlow != curlatchlow) |
817 | process_changeinlatch(oldlatchlow, |
818 | curlatchlow, |
819 | pslot->ctrl); |
820 | } |
821 | } |
822 | } |
823 | ++poll_count; |
824 | poll_state = POLL_SLEEP; |
825 | break; |
826 | case POLL_SLOTS: |
827 | list_for_each_entry(pslot, &ibmphp_slot_head, |
828 | ibm_slot_list) { |
829 | // make a copy of the old status |
830 | memcpy((void *) &myslot, (void *) pslot, |
831 | sizeof(struct slot)); |
832 | rc = ibmphp_hpc_readslot(pslot, READ_ALLSTAT, NULL); |
833 | if ((myslot.status != pslot->status) |
834 | || (myslot.ext_status != pslot->ext_status)) |
835 | process_changeinstatus(pslot, &myslot); |
836 | } |
837 | ctrl_count = 0x00; |
838 | list_for_each_entry(pslot, &ibmphp_slot_head, |
839 | ibm_slot_list) { |
840 | if (ctrl_count >= ibmphp_get_total_controllers()) |
841 | break; |
842 | if (pslot->ctrl->ctlr_relative_id == ctrl_count) { |
843 | ctrl_count++; |
844 | if (READ_SLOT_LATCH(pslot->ctrl)) |
845 | rc = ibmphp_hpc_readslot(pslot, |
846 | READ_SLOTLATCHLOWREG, |
847 | pstatus: &curlatchlow); |
848 | } |
849 | } |
850 | ++poll_count; |
851 | poll_state = POLL_SLEEP; |
852 | break; |
853 | case POLL_SLEEP: |
854 | /* don't sleep with a lock on the hardware */ |
855 | mutex_unlock(lock: &operations_mutex); |
856 | msleep(POLL_INTERVAL_SEC * 1000); |
857 | |
858 | if (kthread_should_stop()) |
859 | goto out_sleep; |
860 | |
861 | mutex_lock(&operations_mutex); |
862 | |
863 | if (poll_count >= POLL_LATCH_CNT) { |
864 | poll_count = 0; |
865 | poll_state = POLL_SLOTS; |
866 | } else |
867 | poll_state = POLL_LATCH_REGISTER; |
868 | break; |
869 | } |
870 | /* give up the hardware semaphore */ |
871 | mutex_unlock(lock: &operations_mutex); |
872 | /* sleep for a short time just for good measure */ |
873 | out_sleep: |
874 | msleep(msecs: 100); |
875 | } |
876 | complete(&exit_complete); |
877 | debug("%s - Exit\n" , __func__); |
878 | return 0; |
879 | } |
880 | |
881 | |
882 | /*---------------------------------------------------------------------- |
883 | * Name: process_changeinstatus |
884 | * |
885 | * Action: compare old and new slot status, process the change in status |
886 | * |
887 | * Input: pointer to slot struct, old slot struct |
888 | * |
889 | * Return 0 or error codes |
890 | * Value: |
891 | * |
892 | * Side |
893 | * Effects: None. |
894 | * |
895 | * Notes: |
896 | *---------------------------------------------------------------------*/ |
897 | static int process_changeinstatus(struct slot *pslot, struct slot *poldslot) |
898 | { |
899 | u8 status; |
900 | int rc = 0; |
901 | u8 disable = 0; |
902 | u8 update = 0; |
903 | |
904 | debug("process_changeinstatus - Entry pslot[%p], poldslot[%p]\n" , pslot, poldslot); |
905 | |
906 | // bit 0 - HPC_SLOT_POWER |
907 | if ((pslot->status & 0x01) != (poldslot->status & 0x01)) |
908 | update = 1; |
909 | |
910 | // bit 1 - HPC_SLOT_CONNECT |
911 | // ignore |
912 | |
913 | // bit 2 - HPC_SLOT_ATTN |
914 | if ((pslot->status & 0x04) != (poldslot->status & 0x04)) |
915 | update = 1; |
916 | |
917 | // bit 3 - HPC_SLOT_PRSNT2 |
918 | // bit 4 - HPC_SLOT_PRSNT1 |
919 | if (((pslot->status & 0x08) != (poldslot->status & 0x08)) |
920 | || ((pslot->status & 0x10) != (poldslot->status & 0x10))) |
921 | update = 1; |
922 | |
923 | // bit 5 - HPC_SLOT_PWRGD |
924 | if ((pslot->status & 0x20) != (poldslot->status & 0x20)) |
925 | // OFF -> ON: ignore, ON -> OFF: disable slot |
926 | if ((poldslot->status & 0x20) && (SLOT_CONNECT(poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT(poldslot->status))) |
927 | disable = 1; |
928 | |
929 | // bit 6 - HPC_SLOT_BUS_SPEED |
930 | // ignore |
931 | |
932 | // bit 7 - HPC_SLOT_LATCH |
933 | if ((pslot->status & 0x80) != (poldslot->status & 0x80)) { |
934 | update = 1; |
935 | // OPEN -> CLOSE |
936 | if (pslot->status & 0x80) { |
937 | if (SLOT_PWRGD(pslot->status)) { |
938 | // power goes on and off after closing latch |
939 | // check again to make sure power is still ON |
940 | msleep(msecs: 1000); |
941 | rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS, pstatus: &status); |
942 | if (SLOT_PWRGD(status)) |
943 | update = 1; |
944 | else // overwrite power in pslot to OFF |
945 | pslot->status &= ~HPC_SLOT_POWER; |
946 | } |
947 | } |
948 | // CLOSE -> OPEN |
949 | else if ((SLOT_PWRGD(poldslot->status) == HPC_SLOT_PWRGD_GOOD) |
950 | && (SLOT_CONNECT(poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT(poldslot->status))) { |
951 | disable = 1; |
952 | } |
953 | // else - ignore |
954 | } |
955 | // bit 4 - HPC_SLOT_BLINK_ATTN |
956 | if ((pslot->ext_status & 0x08) != (poldslot->ext_status & 0x08)) |
957 | update = 1; |
958 | |
959 | if (disable) { |
960 | debug("process_changeinstatus - disable slot\n" ); |
961 | pslot->flag = 0; |
962 | rc = ibmphp_do_disable_slot(slot_cur: pslot); |
963 | } |
964 | |
965 | if (update || disable) |
966 | ibmphp_update_slot_info(pslot); |
967 | |
968 | debug("%s - Exit rc[%d] disable[%x] update[%x]\n" , __func__, rc, disable, update); |
969 | |
970 | return rc; |
971 | } |
972 | |
973 | /*---------------------------------------------------------------------- |
974 | * Name: process_changeinlatch |
975 | * |
976 | * Action: compare old and new latch reg status, process the change |
977 | * |
978 | * Input: old and current latch register status |
979 | * |
980 | * Return 0 or error codes |
981 | * Value: |
982 | *---------------------------------------------------------------------*/ |
983 | static int process_changeinlatch(u8 old, u8 new, struct controller *ctrl) |
984 | { |
985 | struct slot myslot, *pslot; |
986 | u8 i; |
987 | u8 mask; |
988 | int rc = 0; |
989 | |
990 | debug("%s - Entry old[%x], new[%x]\n" , __func__, old, new); |
991 | // bit 0 reserved, 0 is LSB, check bit 1-6 for 6 slots |
992 | |
993 | for (i = ctrl->starting_slot_num; i <= ctrl->ending_slot_num; i++) { |
994 | mask = 0x01 << i; |
995 | if ((mask & old) != (mask & new)) { |
996 | pslot = ibmphp_get_slot_from_physical_num(i); |
997 | if (pslot) { |
998 | memcpy((void *) &myslot, (void *) pslot, sizeof(struct slot)); |
999 | rc = ibmphp_hpc_readslot(pslot, READ_ALLSTAT, NULL); |
1000 | debug("%s - call process_changeinstatus for slot[%d]\n" , __func__, i); |
1001 | process_changeinstatus(pslot, poldslot: &myslot); |
1002 | } else { |
1003 | rc = -EINVAL; |
1004 | err("%s - Error bad pointer for slot[%d]\n" , __func__, i); |
1005 | } |
1006 | } |
1007 | } |
1008 | debug("%s - Exit rc[%d]\n" , __func__, rc); |
1009 | return rc; |
1010 | } |
1011 | |
1012 | /*---------------------------------------------------------------------- |
1013 | * Name: ibmphp_hpc_start_poll_thread |
1014 | * |
1015 | * Action: start polling thread |
1016 | *---------------------------------------------------------------------*/ |
1017 | int __init ibmphp_hpc_start_poll_thread(void) |
1018 | { |
1019 | debug("%s - Entry\n" , __func__); |
1020 | |
1021 | ibmphp_poll_thread = kthread_run(poll_hpc, NULL, "hpc_poll" ); |
1022 | if (IS_ERR(ptr: ibmphp_poll_thread)) { |
1023 | err("%s - Error, thread not started\n" , __func__); |
1024 | return PTR_ERR(ptr: ibmphp_poll_thread); |
1025 | } |
1026 | return 0; |
1027 | } |
1028 | |
1029 | /*---------------------------------------------------------------------- |
1030 | * Name: ibmphp_hpc_stop_poll_thread |
1031 | * |
1032 | * Action: stop polling thread and cleanup |
1033 | *---------------------------------------------------------------------*/ |
1034 | void __exit ibmphp_hpc_stop_poll_thread(void) |
1035 | { |
1036 | debug("%s - Entry\n" , __func__); |
1037 | |
1038 | kthread_stop(k: ibmphp_poll_thread); |
1039 | debug("before locking operations\n" ); |
1040 | ibmphp_lock_operations(); |
1041 | debug("after locking operations\n" ); |
1042 | |
1043 | // wait for poll thread to exit |
1044 | debug("before exit_complete down\n" ); |
1045 | wait_for_completion(&exit_complete); |
1046 | debug("after exit_completion down\n" ); |
1047 | |
1048 | // cleanup |
1049 | debug("before free_hpc_access\n" ); |
1050 | free_hpc_access(); |
1051 | debug("after free_hpc_access\n" ); |
1052 | ibmphp_unlock_operations(); |
1053 | debug("after unlock operations\n" ); |
1054 | |
1055 | debug("%s - Exit\n" , __func__); |
1056 | } |
1057 | |
1058 | /*---------------------------------------------------------------------- |
1059 | * Name: hpc_wait_ctlr_notworking |
1060 | * |
1061 | * Action: wait until the controller is in a not working state |
1062 | * |
1063 | * Return 0, HPC_ERROR |
1064 | * Value: |
1065 | *---------------------------------------------------------------------*/ |
1066 | static int hpc_wait_ctlr_notworking(int timeout, struct controller *ctlr_ptr, void __iomem *wpg_bbar, |
1067 | u8 *pstatus) |
1068 | { |
1069 | int rc = 0; |
1070 | u8 done = 0; |
1071 | |
1072 | debug_polling("hpc_wait_ctlr_notworking - Entry timeout[%d]\n" , timeout); |
1073 | |
1074 | while (!done) { |
1075 | *pstatus = ctrl_read(ctlr: ctlr_ptr, base: wpg_bbar, WPG_CTLR_INDEX); |
1076 | if (*pstatus == HPC_ERROR) { |
1077 | rc = HPC_ERROR; |
1078 | done = 1; |
1079 | } |
1080 | if (CTLR_WORKING(*pstatus) == HPC_CTLR_WORKING_NO) |
1081 | done = 1; |
1082 | if (!done) { |
1083 | msleep(msecs: 1000); |
1084 | if (timeout < 1) { |
1085 | done = 1; |
1086 | err("HPCreadslot - Error ctlr timeout\n" ); |
1087 | rc = HPC_ERROR; |
1088 | } else |
1089 | timeout--; |
1090 | } |
1091 | } |
1092 | debug_polling("hpc_wait_ctlr_notworking - Exit rc[%x] status[%x]\n" , rc, *pstatus); |
1093 | return rc; |
1094 | } |
1095 | |