1/* 2 * HP i8042-based System Device Controller driver. 3 * 4 * Copyright (c) 2001 Brian S. Julin 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions, and the following disclaimer, 12 * without modification. 13 * 2. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * Alternatively, this software may be distributed under the terms of the 17 * GNU General Public License ("GPL"). 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * 29 * References: 30 * System Device Controller Microprocessor Firmware Theory of Operation 31 * for Part Number 1820-4784 Revision B. Dwg No. A-1820-4784-2 32 * Helge Deller's original hilkbd.c port for PA-RISC. 33 * 34 * 35 * Driver theory of operation: 36 * 37 * hp_sdc_put does all writing to the SDC. ISR can run on a different 38 * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time 39 * (it cannot really benefit from SMP anyway.) A tasket fit this perfectly. 40 * 41 * All data coming back from the SDC is sent via interrupt and can be read 42 * fully in the ISR, so there are no latency/throughput problems there. 43 * The problem is with output, due to the slow clock speed of the SDC 44 * compared to the CPU. This should not be too horrible most of the time, 45 * but if used with HIL devices that support the multibyte transfer command, 46 * keeping outbound throughput flowing at the 6500KBps that the HIL is 47 * capable of is more than can be done at HZ=100. 48 * 49 * Busy polling for IBF clear wastes CPU cycles and bus cycles. hp_sdc.ibf 50 * is set to 0 when the IBF flag in the status register has cleared. ISR 51 * may do this, and may also access the parts of queued transactions related 52 * to reading data back from the SDC, but otherwise will not touch the 53 * hp_sdc state. Whenever a register is written hp_sdc.ibf is set to 1. 54 * 55 * The i8042 write index and the values in the 4-byte input buffer 56 * starting at 0x70 are kept track of in hp_sdc.wi, and .r7[], respectively, 57 * to minimize the amount of IO needed to the SDC. However these values 58 * do not need to be locked since they are only ever accessed by hp_sdc_put. 59 * 60 * A timer task schedules the tasklet once per second just to make 61 * sure it doesn't freeze up and to allow for bad reads to time out. 62 */ 63 64#include <linux/hp_sdc.h> 65#include <linux/errno.h> 66#include <linux/init.h> 67#include <linux/module.h> 68#include <linux/ioport.h> 69#include <linux/time.h> 70#include <linux/slab.h> 71#include <linux/hil.h> 72#include <asm/io.h> 73#include <asm/system.h> 74 75/* Machine-specific abstraction */ 76 77#if defined(__hppa__) 78# include <asm/parisc-device.h> 79# define sdc_readb(p) gsc_readb(p) 80# define sdc_writeb(v,p) gsc_writeb((v),(p)) 81#elif defined(__mc68000__) 82# include <asm/uaccess.h> 83# define sdc_readb(p) in_8(p) 84# define sdc_writeb(v,p) out_8((p),(v)) 85#else 86# error "HIL is not supported on this platform" 87#endif 88 89#define PREFIX "HP SDC: " 90 91MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>"); 92MODULE_DESCRIPTION("HP i8042-based SDC Driver"); 93MODULE_LICENSE("Dual BSD/GPL"); 94 95EXPORT_SYMBOL(hp_sdc_request_timer_irq); 96EXPORT_SYMBOL(hp_sdc_request_hil_irq); 97EXPORT_SYMBOL(hp_sdc_request_cooked_irq); 98 99EXPORT_SYMBOL(hp_sdc_release_timer_irq); 100EXPORT_SYMBOL(hp_sdc_release_hil_irq); 101EXPORT_SYMBOL(hp_sdc_release_cooked_irq); 102 103EXPORT_SYMBOL(__hp_sdc_enqueue_transaction); 104EXPORT_SYMBOL(hp_sdc_enqueue_transaction); 105EXPORT_SYMBOL(hp_sdc_dequeue_transaction); 106 107static hp_i8042_sdc hp_sdc; /* All driver state is kept in here. */ 108 109/*************** primitives for use in any context *********************/ 110static inline uint8_t hp_sdc_status_in8(void) 111{ 112 uint8_t status; 113 unsigned long flags; 114 115 write_lock_irqsave(&hp_sdc.ibf_lock, flags); 116 status = sdc_readb(hp_sdc.status_io); 117 if (!(status & HP_SDC_STATUS_IBF)) 118 hp_sdc.ibf = 0; 119 write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); 120 121 return status; 122} 123 124static inline uint8_t hp_sdc_data_in8(void) 125{ 126 return sdc_readb(hp_sdc.data_io); 127} 128 129static inline void hp_sdc_status_out8(uint8_t val) 130{ 131 unsigned long flags; 132 133 write_lock_irqsave(&hp_sdc.ibf_lock, flags); 134 hp_sdc.ibf = 1; 135 if ((val & 0xf0) == 0xe0) 136 hp_sdc.wi = 0xff; 137 sdc_writeb(val, hp_sdc.status_io); 138 write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); 139} 140 141static inline void hp_sdc_data_out8(uint8_t val) 142{ 143 unsigned long flags; 144 145 write_lock_irqsave(&hp_sdc.ibf_lock, flags); 146 hp_sdc.ibf = 1; 147 sdc_writeb(val, hp_sdc.data_io); 148 write_unlock_irqrestore(&hp_sdc.ibf_lock, flags); 149} 150 151/* Care must be taken to only invoke hp_sdc_spin_ibf when 152 * absolutely needed, or in rarely invoked subroutines. 153 * Not only does it waste CPU cycles, it also wastes bus cycles. 154 */ 155static inline void hp_sdc_spin_ibf(void) 156{ 157 unsigned long flags; 158 rwlock_t *lock; 159 160 lock = &hp_sdc.ibf_lock; 161 162 read_lock_irqsave(lock, flags); 163 if (!hp_sdc.ibf) { 164 read_unlock_irqrestore(lock, flags); 165 return; 166 } 167 read_unlock(lock); 168 write_lock(lock); 169 while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF) 170 { } 171 hp_sdc.ibf = 0; 172 write_unlock_irqrestore(lock, flags); 173} 174 175 176/************************ Interrupt context functions ************************/ 177static void hp_sdc_take(int irq, void *dev_id, uint8_t status, uint8_t data) 178{ 179 hp_sdc_transaction *curr; 180 181 read_lock(&hp_sdc.rtq_lock); 182 if (hp_sdc.rcurr < 0) { 183 read_unlock(&hp_sdc.rtq_lock); 184 return; 185 } 186 curr = hp_sdc.tq[hp_sdc.rcurr]; 187 read_unlock(&hp_sdc.rtq_lock); 188 189 curr->seq[curr->idx++] = status; 190 curr->seq[curr->idx++] = data; 191 hp_sdc.rqty -= 2; 192 do_gettimeofday(&hp_sdc.rtv); 193 194 if (hp_sdc.rqty <= 0) { 195 /* All data has been gathered. */ 196 if (curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE) 197 if (curr->act.semaphore) 198 up(curr->act.semaphore); 199 200 if (curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK) 201 if (curr->act.irqhook) 202 curr->act.irqhook(irq, dev_id, status, data); 203 204 curr->actidx = curr->idx; 205 curr->idx++; 206 /* Return control of this transaction */ 207 write_lock(&hp_sdc.rtq_lock); 208 hp_sdc.rcurr = -1; 209 hp_sdc.rqty = 0; 210 write_unlock(&hp_sdc.rtq_lock); 211 tasklet_schedule(&hp_sdc.task); 212 } 213} 214 215static irqreturn_t hp_sdc_isr(int irq, void *dev_id) 216{ 217 uint8_t status, data; 218 219 status = hp_sdc_status_in8(); 220 /* Read data unconditionally to advance i8042. */ 221 data = hp_sdc_data_in8(); 222 223 /* For now we are ignoring these until we get the SDC to behave. */ 224 if (((status & 0xf1) == 0x51) && data == 0x82) 225 return IRQ_HANDLED; 226 227 switch (status & HP_SDC_STATUS_IRQMASK) { 228 case 0: /* This case is not documented. */ 229 break; 230 231 case HP_SDC_STATUS_USERTIMER: 232 case HP_SDC_STATUS_PERIODIC: 233 case HP_SDC_STATUS_TIMER: 234 read_lock(&hp_sdc.hook_lock); 235 if (hp_sdc.timer != NULL) 236 hp_sdc.timer(irq, dev_id, status, data); 237 read_unlock(&hp_sdc.hook_lock); 238 break; 239 240 case HP_SDC_STATUS_REG: 241 hp_sdc_take(irq, dev_id, status, data); 242 break; 243 244 case HP_SDC_STATUS_HILCMD: 245 case HP_SDC_STATUS_HILDATA: 246 read_lock(&hp_sdc.hook_lock); 247 if (hp_sdc.hil != NULL) 248 hp_sdc.hil(irq, dev_id, status, data); 249 read_unlock(&hp_sdc.hook_lock); 250 break; 251 252 case HP_SDC_STATUS_PUP: 253 read_lock(&hp_sdc.hook_lock); 254 if (hp_sdc.pup != NULL) 255 hp_sdc.pup(irq, dev_id, status, data); 256 else 257 printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n"); 258 read_unlock(&hp_sdc.hook_lock); 259 break; 260 261 default: 262 read_lock(&hp_sdc.hook_lock); 263 if (hp_sdc.cooked != NULL) 264 hp_sdc.cooked(irq, dev_id, status, data); 265 read_unlock(&hp_sdc.hook_lock); 266 break; 267 } 268 269 return IRQ_HANDLED; 270} 271 272 273static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id) 274{ 275 int status; 276 277 status = hp_sdc_status_in8(); 278 printk(KERN_WARNING PREFIX "NMI !\n"); 279 280 281 return IRQ_HANDLED; 282} 283 284 285/***************** Kernel (tasklet) context functions ****************/ 286 287unsigned long hp_sdc_put(void); 288 289static void hp_sdc_tasklet(unsigned long foo) 290{ 291 write_lock_irq(&hp_sdc.rtq_lock); 292 293 if (hp_sdc.rcurr >= 0) { 294 struct timeval tv; 295 296 do_gettimeofday(&tv); 297 if (tv.tv_sec > hp_sdc.rtv.tv_sec) 298 tv.tv_usec += USEC_PER_SEC; 299 300 if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) { 301 hp_sdc_transaction *curr; 302 uint8_t tmp; 303 304 curr = hp_sdc.tq[hp_sdc.rcurr]; 305 /* If this turns out to be a normal failure mode 306 * we'll need to figure out a way to communicate 307 * it back to the application. and be less verbose. 308 */ 309 printk(KERN_WARNING PREFIX "read timeout (%ius)!\n", 310 tv.tv_usec - hp_sdc.rtv.tv_usec); 311 curr->idx += hp_sdc.rqty; 312 hp_sdc.rqty = 0; 313 tmp = curr->seq[curr->actidx]; 314 curr->seq[curr->actidx] |= HP_SDC_ACT_DEAD; 315 if (tmp & HP_SDC_ACT_SEMAPHORE) 316 if (curr->act.semaphore) 317 up(curr->act.semaphore); 318 319 if (tmp & HP_SDC_ACT_CALLBACK) { 320 /* Note this means that irqhooks may be called 321 * in tasklet/bh context. 322 */ 323 if (curr->act.irqhook) 324 curr->act.irqhook(0, NULL, 0, 0); 325 } 326 327 curr->actidx = curr->idx; 328 curr->idx++; 329 hp_sdc.rcurr = -1; 330 } 331 } 332 write_unlock_irq(&hp_sdc.rtq_lock); 333 hp_sdc_put(); 334} 335 336unsigned long hp_sdc_put(void) 337{ 338 hp_sdc_transaction *curr; 339 uint8_t act; 340 int idx, curridx; 341 342 int limit = 0; 343 344 write_lock(&hp_sdc.lock); 345 346 /* If i8042 buffers are full, we cannot do anything that 347 requires output, so we skip to the administrativa. */ 348 if (hp_sdc.ibf) { 349 hp_sdc_status_in8(); 350 if (hp_sdc.ibf) 351 goto finish; 352 } 353 354 anew: 355 /* See if we are in the middle of a sequence. */ 356 if (hp_sdc.wcurr < 0) 357 hp_sdc.wcurr = 0; 358 read_lock_irq(&hp_sdc.rtq_lock); 359 if (hp_sdc.rcurr == hp_sdc.wcurr) 360 hp_sdc.wcurr++; 361 read_unlock_irq(&hp_sdc.rtq_lock); 362 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) 363 hp_sdc.wcurr = 0; 364 curridx = hp_sdc.wcurr; 365 366 if (hp_sdc.tq[curridx] != NULL) 367 goto start; 368 369 while (++curridx != hp_sdc.wcurr) { 370 if (curridx >= HP_SDC_QUEUE_LEN) { 371 curridx = -1; /* Wrap to top */ 372 continue; 373 } 374 read_lock_irq(&hp_sdc.rtq_lock); 375 if (hp_sdc.rcurr == curridx) { 376 read_unlock_irq(&hp_sdc.rtq_lock); 377 continue; 378 } 379 read_unlock_irq(&hp_sdc.rtq_lock); 380 if (hp_sdc.tq[curridx] != NULL) 381 break; /* Found one. */ 382 } 383 if (curridx == hp_sdc.wcurr) { /* There's nothing queued to do. */ 384 curridx = -1; 385 } 386 hp_sdc.wcurr = curridx; 387 388 start: 389 390 /* Check to see if the interrupt mask needs to be set. */ 391 if (hp_sdc.set_im) { 392 hp_sdc_status_out8(hp_sdc.im | HP_SDC_CMD_SET_IM); 393 hp_sdc.set_im = 0; 394 goto finish; 395 } 396 397 if (hp_sdc.wcurr == -1) 398 goto done; 399 400 curr = hp_sdc.tq[curridx]; 401 idx = curr->actidx; 402 403 if (curr->actidx >= curr->endidx) { 404 hp_sdc.tq[curridx] = NULL; 405 /* Interleave outbound data between the transactions. */ 406 hp_sdc.wcurr++; 407 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) 408 hp_sdc.wcurr = 0; 409 goto finish; 410 } 411 412 act = curr->seq[idx]; 413 idx++; 414 415 if (curr->idx >= curr->endidx) { 416 if (act & HP_SDC_ACT_DEALLOC) 417 kfree(curr); 418 hp_sdc.tq[curridx] = NULL; 419 /* Interleave outbound data between the transactions. */ 420 hp_sdc.wcurr++; 421 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) 422 hp_sdc.wcurr = 0; 423 goto finish; 424 } 425 426 while (act & HP_SDC_ACT_PRECMD) { 427 if (curr->idx != idx) { 428 idx++; 429 act &= ~HP_SDC_ACT_PRECMD; 430 break; 431 } 432 hp_sdc_status_out8(curr->seq[idx]); 433 curr->idx++; 434 /* act finished? */ 435 if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_PRECMD) 436 goto actdone; 437 /* skip quantity field if data-out sequence follows. */ 438 if (act & HP_SDC_ACT_DATAOUT) 439 curr->idx++; 440 goto finish; 441 } 442 if (act & HP_SDC_ACT_DATAOUT) { 443 int qty; 444 445 qty = curr->seq[idx]; 446 idx++; 447 if (curr->idx - idx < qty) { 448 hp_sdc_data_out8(curr->seq[curr->idx]); 449 curr->idx++; 450 /* act finished? */ 451 if (curr->idx - idx >= qty && 452 (act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT) 453 goto actdone; 454 goto finish; 455 } 456 idx += qty; 457 act &= ~HP_SDC_ACT_DATAOUT; 458 } else 459 while (act & HP_SDC_ACT_DATAREG) { 460 int mask; 461 uint8_t w7[4]; 462 463 mask = curr->seq[idx]; 464 if (idx != curr->idx) { 465 idx++; 466 idx += !!(mask & 1); 467 idx += !!(mask & 2); 468 idx += !!(mask & 4); 469 idx += !!(mask & 8); 470 act &= ~HP_SDC_ACT_DATAREG; 471 break; 472 } 473 474 w7[0] = (mask & 1) ? curr->seq[++idx] : hp_sdc.r7[0]; 475 w7[1] = (mask & 2) ? curr->seq[++idx] : hp_sdc.r7[1]; 476 w7[2] = (mask & 4) ? curr->seq[++idx] : hp_sdc.r7[2]; 477 w7[3] = (mask & 8) ? curr->seq[++idx] : hp_sdc.r7[3]; 478 479 if (hp_sdc.wi > 0x73 || hp_sdc.wi < 0x70 || 480 w7[hp_sdc.wi - 0x70] == hp_sdc.r7[hp_sdc.wi - 0x70]) { 481 int i = 0; 482 483 /* Need to point the write index register */ 484 while (i < 4 && w7[i] == hp_sdc.r7[i]) 485 i++; 486 487 if (i < 4) { 488 hp_sdc_status_out8(HP_SDC_CMD_SET_D0 + i); 489 hp_sdc.wi = 0x70 + i; 490 goto finish; 491 } 492 493 idx++; 494 if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG) 495 goto actdone; 496 497 curr->idx = idx; 498 act &= ~HP_SDC_ACT_DATAREG; 499 break; 500 } 501 502 hp_sdc_data_out8(w7[hp_sdc.wi - 0x70]); 503 hp_sdc.r7[hp_sdc.wi - 0x70] = w7[hp_sdc.wi - 0x70]; 504 hp_sdc.wi++; /* write index register autoincrements */ 505 { 506 int i = 0; 507 508 while ((i < 4) && w7[i] == hp_sdc.r7[i]) 509 i++; 510 if (i >= 4) { 511 curr->idx = idx + 1; 512 if ((act & HP_SDC_ACT_DURING) == 513 HP_SDC_ACT_DATAREG) 514 goto actdone; 515 } 516 } 517 goto finish; 518 } 519 /* We don't go any further in the command if there is a pending read, 520 because we don't want interleaved results. */ 521 read_lock_irq(&hp_sdc.rtq_lock); 522 if (hp_sdc.rcurr >= 0) { 523 read_unlock_irq(&hp_sdc.rtq_lock); 524 goto finish; 525 } 526 read_unlock_irq(&hp_sdc.rtq_lock); 527 528 529 if (act & HP_SDC_ACT_POSTCMD) { 530 uint8_t postcmd; 531 532 /* curr->idx should == idx at this point. */ 533 postcmd = curr->seq[idx]; 534 curr->idx++; 535 if (act & HP_SDC_ACT_DATAIN) { 536 537 /* Start a new read */ 538 hp_sdc.rqty = curr->seq[curr->idx]; 539 do_gettimeofday(&hp_sdc.rtv); 540 curr->idx++; 541 /* Still need to lock here in case of spurious irq. */ 542 write_lock_irq(&hp_sdc.rtq_lock); 543 hp_sdc.rcurr = curridx; 544 write_unlock_irq(&hp_sdc.rtq_lock); 545 hp_sdc_status_out8(postcmd); 546 goto finish; 547 } 548 hp_sdc_status_out8(postcmd); 549 goto actdone; 550 } 551 552 actdone: 553 if (act & HP_SDC_ACT_SEMAPHORE) 554 up(curr->act.semaphore); 555 else if (act & HP_SDC_ACT_CALLBACK) 556 curr->act.irqhook(0,NULL,0,0); 557 558 if (curr->idx >= curr->endidx) { /* This transaction is over. */ 559 if (act & HP_SDC_ACT_DEALLOC) 560 kfree(curr); 561 hp_sdc.tq[curridx] = NULL; 562 } else { 563 curr->actidx = idx + 1; 564 curr->idx = idx + 2; 565 } 566 /* Interleave outbound data between the transactions. */ 567 hp_sdc.wcurr++; 568 if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) 569 hp_sdc.wcurr = 0; 570 571 finish: 572 /* If by some quirk IBF has cleared and our ISR has run to 573 see that that has happened, do it all again. */ 574 if (!hp_sdc.ibf && limit++ < 20) 575 goto anew; 576 577 done: 578 if (hp_sdc.wcurr >= 0) 579 tasklet_schedule(&hp_sdc.task); 580 write_unlock(&hp_sdc.lock); 581 582 return 0; 583} 584 585/******* Functions called in either user or kernel context ****/ 586int __hp_sdc_enqueue_transaction(hp_sdc_transaction *this) 587{ 588 int i; 589 590 if (this == NULL) { 591 BUG(); 592 return -EINVAL; 593 } 594 595 /* Can't have same transaction on queue twice */ 596 for (i = 0; i < HP_SDC_QUEUE_LEN; i++) 597 if (hp_sdc.tq[i] == this) 598 goto fail; 599 600 this->actidx = 0; 601 this->idx = 1; 602 603 /* Search for empty slot */ 604 for (i = 0; i < HP_SDC_QUEUE_LEN; i++) 605 if (hp_sdc.tq[i] == NULL) { 606 hp_sdc.tq[i] = this; 607 tasklet_schedule(&hp_sdc.task); 608 return 0; 609 } 610 611 printk(KERN_WARNING PREFIX "No free slot to add transaction.\n"); 612 return -EBUSY; 613 614 fail: 615 printk(KERN_WARNING PREFIX "Transaction add failed: transaction already queued?\n"); 616 return -EINVAL; 617} 618 619int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) { 620 unsigned long flags; 621 int ret; 622 623 write_lock_irqsave(&hp_sdc.lock, flags); 624 ret = __hp_sdc_enqueue_transaction(this); 625 write_unlock_irqrestore(&hp_sdc.lock,flags); 626 627 return ret; 628} 629 630int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) 631{ 632 unsigned long flags; 633 int i; 634 635 write_lock_irqsave(&hp_sdc.lock, flags); 636 637 /* TODO: don't remove it if it's not done. */ 638 639 for (i = 0; i < HP_SDC_QUEUE_LEN; i++) 640 if (hp_sdc.tq[i] == this) 641 hp_sdc.tq[i] = NULL; 642 643 write_unlock_irqrestore(&hp_sdc.lock, flags); 644 return 0; 645} 646 647 648 649/********************** User context functions **************************/ 650int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback) 651{ 652 if (callback == NULL || hp_sdc.dev == NULL) 653 return -EINVAL; 654 655 write_lock_irq(&hp_sdc.hook_lock); 656 if (hp_sdc.timer != NULL) { 657 write_unlock_irq(&hp_sdc.hook_lock); 658 return -EBUSY; 659 } 660 661 hp_sdc.timer = callback; 662 /* Enable interrupts from the timers */ 663 hp_sdc.im &= ~HP_SDC_IM_FH; 664 hp_sdc.im &= ~HP_SDC_IM_PT; 665 hp_sdc.im &= ~HP_SDC_IM_TIMERS; 666 hp_sdc.set_im = 1; 667 write_unlock_irq(&hp_sdc.hook_lock); 668 669 tasklet_schedule(&hp_sdc.task); 670 671 return 0; 672} 673 674int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback) 675{ 676 if (callback == NULL || hp_sdc.dev == NULL) 677 return -EINVAL; 678 679 write_lock_irq(&hp_sdc.hook_lock); 680 if (hp_sdc.hil != NULL) { 681 write_unlock_irq(&hp_sdc.hook_lock); 682 return -EBUSY; 683 } 684 685 hp_sdc.hil = callback; 686 hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET); 687 hp_sdc.set_im = 1; 688 write_unlock_irq(&hp_sdc.hook_lock); 689 690 tasklet_schedule(&hp_sdc.task); 691 692 return 0; 693} 694 695int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback) 696{ 697 if (callback == NULL || hp_sdc.dev == NULL) 698 return -EINVAL; 699 700 write_lock_irq(&hp_sdc.hook_lock); 701 if (hp_sdc.cooked != NULL) { 702 write_unlock_irq(&hp_sdc.hook_lock); 703 return -EBUSY; 704 } 705 706 /* Enable interrupts from the HIL MLC */ 707 hp_sdc.cooked = callback; 708 hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET); 709 hp_sdc.set_im = 1; 710 write_unlock_irq(&hp_sdc.hook_lock); 711 712 tasklet_schedule(&hp_sdc.task); 713 714 return 0; 715} 716 717int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback) 718{ 719 write_lock_irq(&hp_sdc.hook_lock); 720 if ((callback != hp_sdc.timer) || 721 (hp_sdc.timer == NULL)) { 722 write_unlock_irq(&hp_sdc.hook_lock); 723 return -EINVAL; 724 } 725 726 /* Disable interrupts from the timers */ 727 hp_sdc.timer = NULL; 728 hp_sdc.im |= HP_SDC_IM_TIMERS; 729 hp_sdc.im |= HP_SDC_IM_FH; 730 hp_sdc.im |= HP_SDC_IM_PT; 731 hp_sdc.set_im = 1; 732 write_unlock_irq(&hp_sdc.hook_lock); 733 tasklet_schedule(&hp_sdc.task); 734 735 return 0; 736} 737 738int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback) 739{ 740 write_lock_irq(&hp_sdc.hook_lock); 741 if ((callback != hp_sdc.hil) || 742 (hp_sdc.hil == NULL)) { 743 write_unlock_irq(&hp_sdc.hook_lock); 744 return -EINVAL; 745 } 746 747 hp_sdc.hil = NULL; 748 /* Disable interrupts from HIL only if there is no cooked driver. */ 749 if(hp_sdc.cooked == NULL) { 750 hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET); 751 hp_sdc.set_im = 1; 752 } 753 write_unlock_irq(&hp_sdc.hook_lock); 754 tasklet_schedule(&hp_sdc.task); 755 756 return 0; 757} 758 759int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) 760{ 761 write_lock_irq(&hp_sdc.hook_lock); 762 if ((callback != hp_sdc.cooked) || 763 (hp_sdc.cooked == NULL)) { 764 write_unlock_irq(&hp_sdc.hook_lock); 765 return -EINVAL; 766 } 767 768 hp_sdc.cooked = NULL; 769 /* Disable interrupts from HIL only if there is no raw HIL driver. */ 770 if(hp_sdc.hil == NULL) { 771 hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET); 772 hp_sdc.set_im = 1; 773 } 774 write_unlock_irq(&hp_sdc.hook_lock); 775 tasklet_schedule(&hp_sdc.task); 776 777 return 0; 778} 779 780/************************* Keepalive timer task *********************/ 781 782void hp_sdc_kicker (unsigned long data) 783{ 784 tasklet_schedule(&hp_sdc.task); 785 /* Re-insert the periodic task. */ 786 mod_timer(&hp_sdc.kicker, jiffies + HZ); 787} 788 789/************************** Module Initialization ***************************/ 790 791#if defined(__hppa__) 792 793static const struct parisc_device_id hp_sdc_tbl[] = { 794 { 795 .hw_type = HPHW_FIO, 796 .hversion_rev = HVERSION_REV_ANY_ID, 797 .hversion = HVERSION_ANY_ID, 798 .sversion = 0x73, 799 }, 800 { 0, } 801}; 802 803MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl); 804 805static int __init hp_sdc_init_hppa(struct parisc_device *d); 806 807static struct parisc_driver hp_sdc_driver = { 808 .name = "hp_sdc", 809 .id_table = hp_sdc_tbl, 810 .probe = hp_sdc_init_hppa, 811}; 812 813#endif /* __hppa__ */ 814 815static int __init hp_sdc_init(void) 816{ 817 char *errstr; 818 hp_sdc_transaction t_sync; 819 uint8_t ts_sync[6]; 820 struct semaphore s_sync; 821 822 rwlock_init(&hp_sdc.lock); 823 rwlock_init(&hp_sdc.ibf_lock); 824 rwlock_init(&hp_sdc.rtq_lock); 825 rwlock_init(&hp_sdc.hook_lock); 826 827 hp_sdc.timer = NULL; 828 hp_sdc.hil = NULL; 829 hp_sdc.pup = NULL; 830 hp_sdc.cooked = NULL; 831 hp_sdc.im = HP_SDC_IM_MASK; /* Mask maskable irqs */ 832 hp_sdc.set_im = 1; 833 hp_sdc.wi = 0xff; 834 hp_sdc.r7[0] = 0xff; 835 hp_sdc.r7[1] = 0xff; 836 hp_sdc.r7[2] = 0xff; 837 hp_sdc.r7[3] = 0xff; 838 hp_sdc.ibf = 1; 839 840 memset(&hp_sdc.tq, 0, sizeof(hp_sdc.tq)); 841 842 hp_sdc.wcurr = -1; 843 hp_sdc.rcurr = -1; 844 hp_sdc.rqty = 0; 845 846 hp_sdc.dev_err = -ENODEV; 847 848 errstr = "IO not found for"; 849 if (!hp_sdc.base_io) 850 goto err0; 851 852 errstr = "IRQ not found for"; 853 if (!hp_sdc.irq) 854 goto err0; 855 856 hp_sdc.dev_err = -EBUSY; 857 858#if defined(__hppa__) 859 errstr = "IO not available for"; 860 if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name)) 861 goto err0; 862#endif 863 864 errstr = "IRQ not available for"; 865 if (request_irq(hp_sdc.irq, &hp_sdc_isr, IRQF_SHARED|IRQF_SAMPLE_RANDOM, 866 "HP SDC", &hp_sdc)) 867 goto err1; 868 869 errstr = "NMI not available for"; 870 if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, IRQF_SHARED, 871 "HP SDC NMI", &hp_sdc)) 872 goto err2; 873 874 printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n", 875 (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi); 876 877 hp_sdc_status_in8(); 878 hp_sdc_data_in8(); 879 880 tasklet_init(&hp_sdc.task, hp_sdc_tasklet, 0); 881 882 /* Sync the output buffer registers, thus scheduling hp_sdc_tasklet. */ 883 t_sync.actidx = 0; 884 t_sync.idx = 1; 885 t_sync.endidx = 6; 886 t_sync.seq = ts_sync; 887 ts_sync[0] = HP_SDC_ACT_DATAREG | HP_SDC_ACT_SEMAPHORE; 888 ts_sync[1] = 0x0f; 889 ts_sync[2] = ts_sync[3] = ts_sync[4] = ts_sync[5] = 0; 890 t_sync.act.semaphore = &s_sync; 891 init_MUTEX_LOCKED(&s_sync); 892 hp_sdc_enqueue_transaction(&t_sync); 893 down(&s_sync); /* Wait for t_sync to complete */ 894 895 /* Create the keepalive task */ 896 init_timer(&hp_sdc.kicker); 897 hp_sdc.kicker.expires = jiffies + HZ; 898 hp_sdc.kicker.function = &hp_sdc_kicker; 899 add_timer(&hp_sdc.kicker); 900 901 hp_sdc.dev_err = 0; 902 return 0; 903 err2: 904 free_irq(hp_sdc.irq, &hp_sdc); 905 err1: 906 release_region(hp_sdc.data_io, 2); 907 err0: 908 printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n", 909 errstr, (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi); 910 hp_sdc.dev = NULL; 911 912 return hp_sdc.dev_err; 913} 914 915#if defined(__hppa__) 916 917static int __init hp_sdc_init_hppa(struct parisc_device *d) 918{ 919 if (!d) 920 return 1; 921 if (hp_sdc.dev != NULL) 922 return 1; /* We only expect one SDC */ 923 924 hp_sdc.dev = d; 925 hp_sdc.irq = d->irq; 926 hp_sdc.nmi = d->aux_irq; 927 hp_sdc.base_io = d->hpa.start; 928 hp_sdc.data_io = d->hpa.start + 0x800; 929 hp_sdc.status_io = d->hpa.start + 0x801; 930 931 return hp_sdc_init(); 932} 933 934#endif /* __hppa__ */ 935 936#if !defined(__mc68000__) /* Link error on m68k! */ 937static void __exit hp_sdc_exit(void) 938#else 939static void hp_sdc_exit(void) 940#endif 941{ 942 write_lock_irq(&hp_sdc.lock); 943 944 /* Turn off all maskable "sub-function" irq's. */ 945 hp_sdc_spin_ibf(); 946 sdc_writeb(HP_SDC_CMD_SET_IM | HP_SDC_IM_MASK, hp_sdc.status_io); 947 948 /* Wait until we know this has been processed by the i8042 */ 949 hp_sdc_spin_ibf(); 950 951 free_irq(hp_sdc.nmi, &hp_sdc); 952 free_irq(hp_sdc.irq, &hp_sdc); 953 write_unlock_irq(&hp_sdc.lock); 954 955 del_timer(&hp_sdc.kicker); 956 957 tasklet_kill(&hp_sdc.task); 958 959#if defined(__hppa__) 960 if (unregister_parisc_driver(&hp_sdc_driver)) 961 printk(KERN_WARNING PREFIX "Error unregistering HP SDC"); 962#endif 963} 964 965static int __init hp_sdc_register(void) 966{ 967 hp_sdc_transaction tq_init; 968 uint8_t tq_init_seq[5]; 969 struct semaphore tq_init_sem; 970#if defined(__mc68000__) 971 mm_segment_t fs; 972 unsigned char i; 973#endif 974 975 hp_sdc.dev = NULL; 976 hp_sdc.dev_err = 0; 977#if defined(__hppa__) 978 if (register_parisc_driver(&hp_sdc_driver)) { 979 printk(KERN_WARNING PREFIX "Error registering SDC with system bus tree.\n"); 980 return -ENODEV; 981 } 982#elif defined(__mc68000__) 983 if (!MACH_IS_HP300) 984 return -ENODEV; 985 986 hp_sdc.irq = 1; 987 hp_sdc.nmi = 7; 988 hp_sdc.base_io = (unsigned long) 0xf0428000; 989 hp_sdc.data_io = (unsigned long) hp_sdc.base_io + 1; 990 hp_sdc.status_io = (unsigned long) hp_sdc.base_io + 3; 991 fs = get_fs(); 992 set_fs(KERNEL_DS); 993 if (!get_user(i, (unsigned char *)hp_sdc.data_io)) 994 hp_sdc.dev = (void *)1; 995 set_fs(fs); 996 hp_sdc.dev_err = hp_sdc_init(); 997#endif 998 if (hp_sdc.dev == NULL) { 999 printk(KERN_WARNING PREFIX "No SDC found.\n"); 1000 return hp_sdc.dev_err; 1001 } 1002 1003 init_MUTEX_LOCKED(&tq_init_sem); 1004 1005 tq_init.actidx = 0; 1006 tq_init.idx = 1; 1007 tq_init.endidx = 5; 1008 tq_init.seq = tq_init_seq; 1009 tq_init.act.semaphore = &tq_init_sem; 1010 1011 tq_init_seq[0] = 1012 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE; 1013 tq_init_seq[1] = HP_SDC_CMD_READ_KCC; 1014 tq_init_seq[2] = 1; 1015 tq_init_seq[3] = 0; 1016 tq_init_seq[4] = 0; 1017 1018 hp_sdc_enqueue_transaction(&tq_init); 1019 1020 down(&tq_init_sem); 1021 up(&tq_init_sem); 1022 1023 if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) { 1024 printk(KERN_WARNING PREFIX "Error reading config byte.\n"); 1025 hp_sdc_exit(); 1026 return -ENODEV; 1027 } 1028 hp_sdc.r11 = tq_init_seq[4]; 1029 if (hp_sdc.r11 & HP_SDC_CFG_NEW) { 1030 const char *str; 1031 printk(KERN_INFO PREFIX "New style SDC\n"); 1032 tq_init_seq[1] = HP_SDC_CMD_READ_XTD; 1033 tq_init.actidx = 0; 1034 tq_init.idx = 1; 1035 down(&tq_init_sem); 1036 hp_sdc_enqueue_transaction(&tq_init); 1037 down(&tq_init_sem); 1038 up(&tq_init_sem); 1039 if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) { 1040 printk(KERN_WARNING PREFIX "Error reading extended config byte.\n"); 1041 return -ENODEV; 1042 } 1043 hp_sdc.r7e = tq_init_seq[4]; 1044 HP_SDC_XTD_REV_STRINGS(hp_sdc.r7e & HP_SDC_XTD_REV, str) 1045 printk(KERN_INFO PREFIX "Revision: %s\n", str); 1046 if (hp_sdc.r7e & HP_SDC_XTD_BEEPER) 1047 printk(KERN_INFO PREFIX "TI SN76494 beeper present\n"); 1048 if (hp_sdc.r7e & HP_SDC_XTD_BBRTC) 1049 printk(KERN_INFO PREFIX "OKI MSM-58321 BBRTC present\n"); 1050 printk(KERN_INFO PREFIX "Spunking the self test register to force PUP " 1051 "on next firmware reset.\n"); 1052 tq_init_seq[0] = HP_SDC_ACT_PRECMD | 1053 HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE; 1054 tq_init_seq[1] = HP_SDC_CMD_SET_STR; 1055 tq_init_seq[2] = 1; 1056 tq_init_seq[3] = 0; 1057 tq_init.actidx = 0; 1058 tq_init.idx = 1; 1059 tq_init.endidx = 4; 1060 down(&tq_init_sem); 1061 hp_sdc_enqueue_transaction(&tq_init); 1062 down(&tq_init_sem); 1063 up(&tq_init_sem); 1064 } else 1065 printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n", 1066 (hp_sdc.r11 & HP_SDC_CFG_REV) ? "3300" : "2564/3087"); 1067 1068 return 0; 1069} 1070 1071module_init(hp_sdc_register); 1072module_exit(hp_sdc_exit); 1073 1074/* Timing notes: These measurements taken on my 64MHz 7100-LC (715/64) 1075 * cycles cycles-adj time 1076 * between two consecutive mfctl(16)'s: 4 n/a 63ns 1077 * hp_sdc_spin_ibf when idle: 119 115 1.7us 1078 * gsc_writeb status register: 83 79 1.2us 1079 * IBF to clear after sending SET_IM: 6204 6006 93us 1080 * IBF to clear after sending LOAD_RT: 4467 4352 68us 1081 * IBF to clear after sending two LOAD_RTs: 18974 18859 295us 1082 * READ_T1, read status/data, IRQ, call handler: 35564 n/a 556us 1083 * cmd to ~IBF READ_T1 2nd time right after: 5158403 n/a 81ms 1084 * between IRQ received and ~IBF for above: 2578877 n/a 40ms 1085 * 1086 * Performance stats after a run of this module configuring HIL and 1087 * receiving a few mouse events: 1088 * 1089 * status in8 282508 cycles 7128 calls 1090 * status out8 8404 cycles 341 calls 1091 * data out8 1734 cycles 78 calls 1092 * isr 174324 cycles 617 calls (includes take) 1093 * take 1241 cycles 2 calls 1094 * put 1411504 cycles 6937 calls 1095 * task 1655209 cycles 6937 calls (includes put) 1096 * 1097 */ 1098