1/* 2 * Driver for Intel I82092AA PCI-PCMCIA bridge. 3 * 4 * (C) 2001 Red Hat, Inc. 5 * 6 * Author: Arjan Van De Ven <arjanv@redhat.com> 7 * Loosly based on i82365.c from the pcmcia-cs package 8 */ 9 10#include <linux/kernel.h> 11#include <linux/module.h> 12#include <linux/pci.h> 13#include <linux/init.h> 14#include <linux/workqueue.h> 15#include <linux/interrupt.h> 16#include <linux/device.h> 17 18#include <pcmcia/ss.h> 19 20#include <asm/io.h> 21 22#include "i82092aa.h" 23#include "i82365.h" 24 25MODULE_LICENSE("GPL"); 26 27/* PCI core routines */ 28static const struct pci_device_id i82092aa_pci_ids[] = { 29 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82092AA_0) }, 30 { } 31}; 32MODULE_DEVICE_TABLE(pci, i82092aa_pci_ids); 33 34static struct pci_driver i82092aa_pci_driver = { 35 .name = "i82092aa", 36 .id_table = i82092aa_pci_ids, 37 .probe = i82092aa_pci_probe, 38 .remove = i82092aa_pci_remove, 39}; 40 41 42/* the pccard structure and its functions */ 43static struct pccard_operations i82092aa_operations = { 44 .init = i82092aa_init, 45 .get_status = i82092aa_get_status, 46 .set_socket = i82092aa_set_socket, 47 .set_io_map = i82092aa_set_io_map, 48 .set_mem_map = i82092aa_set_mem_map, 49}; 50 51/* The card can do up to 4 sockets, allocate a structure for each of them */ 52 53struct socket_info { 54 int number; 55 int card_state; /* 0 = no socket, 56 1 = empty socket, 57 2 = card but not initialized, 58 3 = operational card */ 59 unsigned int io_base; /* base io address of the socket */ 60 61 struct pcmcia_socket socket; 62 struct pci_dev *dev; /* The PCI device for the socket */ 63}; 64 65#define MAX_SOCKETS 4 66static struct socket_info sockets[MAX_SOCKETS]; 67static int socket_count; /* shortcut */ 68 69 70static int i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) 71{ 72 unsigned char configbyte; 73 int i, ret; 74 75 enter("i82092aa_pci_probe"); 76 77 if ((ret = pci_enable_device(dev))) 78 return ret; 79 80 pci_read_config_byte(dev, 0x40, &configbyte); /* PCI Configuration Control */ 81 switch(configbyte&6) { 82 case 0: 83 socket_count = 2; 84 break; 85 case 2: 86 socket_count = 1; 87 break; 88 case 4: 89 case 6: 90 socket_count = 4; 91 break; 92 93 default: 94 printk(KERN_ERR "i82092aa: Oops, you did something we didn't think of.\n"); 95 ret = -EIO; 96 goto err_out_disable; 97 } 98 printk(KERN_INFO "i82092aa: configured as a %d socket device.\n", socket_count); 99 100 if (!request_region(pci_resource_start(dev, 0), 2, "i82092aa")) { 101 ret = -EBUSY; 102 goto err_out_disable; 103 } 104 105 for (i = 0;i<socket_count;i++) { 106 sockets[i].card_state = 1; /* 1 = present but empty */ 107 sockets[i].io_base = pci_resource_start(dev, 0); 108 sockets[i].socket.features |= SS_CAP_PCCARD; 109 sockets[i].socket.map_size = 0x1000; 110 sockets[i].socket.irq_mask = 0; 111 sockets[i].socket.pci_irq = dev->irq; 112 sockets[i].socket.cb_dev = dev; 113 sockets[i].socket.owner = THIS_MODULE; 114 115 sockets[i].number = i; 116 117 if (card_present(i)) { 118 sockets[i].card_state = 3; 119 dprintk(KERN_DEBUG "i82092aa: slot %i is occupied\n",i); 120 } else { 121 dprintk(KERN_DEBUG "i82092aa: slot %i is vacant\n",i); 122 } 123 } 124 125 /* Now, specifiy that all interrupts are to be done as PCI interrupts */ 126 configbyte = 0xFF; /* bitmask, one bit per event, 1 = PCI interrupt, 0 = ISA interrupt */ 127 pci_write_config_byte(dev, 0x50, configbyte); /* PCI Interrupt Routing Register */ 128 129 /* Register the interrupt handler */ 130 dprintk(KERN_DEBUG "Requesting interrupt %i \n",dev->irq); 131 if ((ret = request_irq(dev->irq, i82092aa_interrupt, IRQF_SHARED, "i82092aa", i82092aa_interrupt))) { 132 printk(KERN_ERR "i82092aa: Failed to register IRQ %d, aborting\n", dev->irq); 133 goto err_out_free_res; 134 } 135 136 for (i = 0; i<socket_count; i++) { 137 sockets[i].socket.dev.parent = &dev->dev; 138 sockets[i].socket.ops = &i82092aa_operations; 139 sockets[i].socket.resource_ops = &pccard_nonstatic_ops; 140 ret = pcmcia_register_socket(&sockets[i].socket); 141 if (ret) { 142 goto err_out_free_sockets; 143 } 144 } 145 146 leave("i82092aa_pci_probe"); 147 return 0; 148 149err_out_free_sockets: 150 if (i) { 151 for (i--;i>=0;i--) { 152 pcmcia_unregister_socket(&sockets[i].socket); 153 } 154 } 155 free_irq(dev->irq, i82092aa_interrupt); 156err_out_free_res: 157 release_region(pci_resource_start(dev, 0), 2); 158err_out_disable: 159 pci_disable_device(dev); 160 return ret; 161} 162 163static void i82092aa_pci_remove(struct pci_dev *dev) 164{ 165 int i; 166 167 enter("i82092aa_pci_remove"); 168 169 free_irq(dev->irq, i82092aa_interrupt); 170 171 for (i = 0; i < socket_count; i++) 172 pcmcia_unregister_socket(&sockets[i].socket); 173 174 leave("i82092aa_pci_remove"); 175} 176 177static DEFINE_SPINLOCK(port_lock); 178 179/* basic value read/write functions */ 180 181static unsigned char indirect_read(int socket, unsigned short reg) 182{ 183 unsigned short int port; 184 unsigned char val; 185 unsigned long flags; 186 spin_lock_irqsave(&port_lock,flags); 187 reg += socket * 0x40; 188 port = sockets[socket].io_base; 189 outb(reg,port); 190 val = inb(port+1); 191 spin_unlock_irqrestore(&port_lock,flags); 192 return val; 193} 194 195#if 0 196static unsigned short indirect_read16(int socket, unsigned short reg) 197{ 198 unsigned short int port; 199 unsigned short tmp; 200 unsigned long flags; 201 spin_lock_irqsave(&port_lock,flags); 202 reg = reg + socket * 0x40; 203 port = sockets[socket].io_base; 204 outb(reg,port); 205 tmp = inb(port+1); 206 reg++; 207 outb(reg,port); 208 tmp = tmp | (inb(port+1)<<8); 209 spin_unlock_irqrestore(&port_lock,flags); 210 return tmp; 211} 212#endif 213 214static void indirect_write(int socket, unsigned short reg, unsigned char value) 215{ 216 unsigned short int port; 217 unsigned long flags; 218 spin_lock_irqsave(&port_lock,flags); 219 reg = reg + socket * 0x40; 220 port = sockets[socket].io_base; 221 outb(reg,port); 222 outb(value,port+1); 223 spin_unlock_irqrestore(&port_lock,flags); 224} 225 226static void indirect_setbit(int socket, unsigned short reg, unsigned char mask) 227{ 228 unsigned short int port; 229 unsigned char val; 230 unsigned long flags; 231 spin_lock_irqsave(&port_lock,flags); 232 reg = reg + socket * 0x40; 233 port = sockets[socket].io_base; 234 outb(reg,port); 235 val = inb(port+1); 236 val |= mask; 237 outb(reg,port); 238 outb(val,port+1); 239 spin_unlock_irqrestore(&port_lock,flags); 240} 241 242 243static void indirect_resetbit(int socket, unsigned short reg, unsigned char mask) 244{ 245 unsigned short int port; 246 unsigned char val; 247 unsigned long flags; 248 spin_lock_irqsave(&port_lock,flags); 249 reg = reg + socket * 0x40; 250 port = sockets[socket].io_base; 251 outb(reg,port); 252 val = inb(port+1); 253 val &= ~mask; 254 outb(reg,port); 255 outb(val,port+1); 256 spin_unlock_irqrestore(&port_lock,flags); 257} 258 259static void indirect_write16(int socket, unsigned short reg, unsigned short value) 260{ 261 unsigned short int port; 262 unsigned char val; 263 unsigned long flags; 264 spin_lock_irqsave(&port_lock,flags); 265 reg = reg + socket * 0x40; 266 port = sockets[socket].io_base; 267 268 outb(reg,port); 269 val = value & 255; 270 outb(val,port+1); 271 272 reg++; 273 274 outb(reg,port); 275 val = value>>8; 276 outb(val,port+1); 277 spin_unlock_irqrestore(&port_lock,flags); 278} 279 280/* simple helper functions */ 281/* External clock time, in nanoseconds. 120 ns = 8.33 MHz */ 282static int cycle_time = 120; 283 284static int to_cycles(int ns) 285{ 286 if (cycle_time!=0) 287 return ns/cycle_time; 288 else 289 return 0; 290} 291 292 293/* Interrupt handler functionality */ 294 295static irqreturn_t i82092aa_interrupt(int irq, void *dev) 296{ 297 int i; 298 int loopcount = 0; 299 int handled = 0; 300 301 unsigned int events, active=0; 302 303/* enter("i82092aa_interrupt");*/ 304 305 while (1) { 306 loopcount++; 307 if (loopcount>20) { 308 printk(KERN_ERR "i82092aa: infinite eventloop in interrupt \n"); 309 break; 310 } 311 312 active = 0; 313 314 for (i=0;i<socket_count;i++) { 315 int csc; 316 if (sockets[i].card_state==0) /* Inactive socket, should not happen */ 317 continue; 318 319 csc = indirect_read(i,I365_CSC); /* card status change register */ 320 321 if (csc==0) /* no events on this socket */ 322 continue; 323 handled = 1; 324 events = 0; 325 326 if (csc & I365_CSC_DETECT) { 327 events |= SS_DETECT; 328 printk("Card detected in socket %i!\n",i); 329 } 330 331 if (indirect_read(i,I365_INTCTL) & I365_PC_IOCARD) { 332 /* For IO/CARDS, bit 0 means "read the card" */ 333 events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0; 334 } else { 335 /* Check for battery/ready events */ 336 events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0; 337 events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0; 338 events |= (csc & I365_CSC_READY) ? SS_READY : 0; 339 } 340 341 if (events) { 342 pcmcia_parse_events(&sockets[i].socket, events); 343 } 344 active |= events; 345 } 346 347 if (active==0) /* no more events to handle */ 348 break; 349 350 } 351 return IRQ_RETVAL(handled); 352/* leave("i82092aa_interrupt");*/ 353} 354 355 356 357/* socket functions */ 358 359static int card_present(int socketno) 360{ 361 unsigned int val; 362 enter("card_present"); 363 364 if ((socketno<0) || (socketno >= MAX_SOCKETS)) 365 return 0; 366 if (sockets[socketno].io_base == 0) 367 return 0; 368 369 370 val = indirect_read(socketno, 1); /* Interface status register */ 371 if ((val&12)==12) { 372 leave("card_present 1"); 373 return 1; 374 } 375 376 leave("card_present 0"); 377 return 0; 378} 379 380static void set_bridge_state(int sock) 381{ 382 enter("set_bridge_state"); 383 indirect_write(sock, I365_GBLCTL,0x00); 384 indirect_write(sock, I365_GENCTL,0x00); 385 386 indirect_setbit(sock, I365_INTCTL,0x08); 387 leave("set_bridge_state"); 388} 389 390 391 392 393 394 395static int i82092aa_init(struct pcmcia_socket *sock) 396{ 397 int i; 398 struct resource res = { .start = 0, .end = 0x0fff }; 399 pccard_io_map io = { 0, 0, 0, 0, 1 }; 400 pccard_mem_map mem = { .res = &res, }; 401 402 enter("i82092aa_init"); 403 404 for (i = 0; i < 2; i++) { 405 io.map = i; 406 i82092aa_set_io_map(sock, &io); 407 } 408 for (i = 0; i < 5; i++) { 409 mem.map = i; 410 i82092aa_set_mem_map(sock, &mem); 411 } 412 413 leave("i82092aa_init"); 414 return 0; 415} 416 417static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value) 418{ 419 unsigned int sock = container_of(socket, struct socket_info, socket)->number; 420 unsigned int status; 421 422 enter("i82092aa_get_status"); 423 424 status = indirect_read(sock,I365_STATUS); /* Interface Status Register */ 425 *value = 0; 426 427 if ((status & I365_CS_DETECT) == I365_CS_DETECT) { 428 *value |= SS_DETECT; 429 } 430 431 /* IO cards have a different meaning of bits 0,1 */ 432 /* Also notice the inverse-logic on the bits */ 433 if (indirect_read(sock, I365_INTCTL) & I365_PC_IOCARD) { 434 /* IO card */ 435 if (!(status & I365_CS_STSCHG)) 436 *value |= SS_STSCHG; 437 } else { /* non I/O card */ 438 if (!(status & I365_CS_BVD1)) 439 *value |= SS_BATDEAD; 440 if (!(status & I365_CS_BVD2)) 441 *value |= SS_BATWARN; 442 443 } 444 445 if (status & I365_CS_WRPROT) 446 (*value) |= SS_WRPROT; /* card is write protected */ 447 448 if (status & I365_CS_READY) 449 (*value) |= SS_READY; /* card is not busy */ 450 451 if (status & I365_CS_POWERON) 452 (*value) |= SS_POWERON; /* power is applied to the card */ 453 454 455 leave("i82092aa_get_status"); 456 return 0; 457} 458 459 460static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *state) 461{ 462 unsigned int sock = container_of(socket, struct socket_info, socket)->number; 463 unsigned char reg; 464 465 enter("i82092aa_set_socket"); 466 467 /* First, set the global controller options */ 468 469 set_bridge_state(sock); 470 471 /* Values for the IGENC register */ 472 473 reg = 0; 474 if (!(state->flags & SS_RESET)) /* The reset bit has "inverse" logic */ 475 reg = reg | I365_PC_RESET; 476 if (state->flags & SS_IOCARD) 477 reg = reg | I365_PC_IOCARD; 478 479 indirect_write(sock,I365_INTCTL,reg); /* IGENC, Interrupt and General Control Register */ 480 481 /* Power registers */ 482 483 reg = I365_PWR_NORESET; /* default: disable resetdrv on resume */ 484 485 if (state->flags & SS_PWR_AUTO) { 486 printk("Auto power\n"); 487 reg |= I365_PWR_AUTO; /* automatic power mngmnt */ 488 } 489 if (state->flags & SS_OUTPUT_ENA) { 490 printk("Power Enabled \n"); 491 reg |= I365_PWR_OUT; /* enable power */ 492 } 493 494 switch (state->Vcc) { 495 case 0: 496 break; 497 case 50: 498 printk("setting voltage to Vcc to 5V on socket %i\n",sock); 499 reg |= I365_VCC_5V; 500 break; 501 default: 502 printk("i82092aa: i82092aa_set_socket called with invalid VCC power value: %i ", state->Vcc); 503 leave("i82092aa_set_socket"); 504 return -EINVAL; 505 } 506 507 508 switch (state->Vpp) { 509 case 0: 510 printk("not setting Vpp on socket %i\n",sock); 511 break; 512 case 50: 513 printk("setting Vpp to 5.0 for socket %i\n",sock); 514 reg |= I365_VPP1_5V | I365_VPP2_5V; 515 break; 516 case 120: 517 printk("setting Vpp to 12.0\n"); 518 reg |= I365_VPP1_12V | I365_VPP2_12V; 519 break; 520 default: 521 printk("i82092aa: i82092aa_set_socket called with invalid VPP power value: %i ", state->Vcc); 522 leave("i82092aa_set_socket"); 523 return -EINVAL; 524 } 525 526 if (reg != indirect_read(sock,I365_POWER)) /* only write if changed */ 527 indirect_write(sock,I365_POWER,reg); 528 529 /* Enable specific interrupt events */ 530 531 reg = 0x00; 532 if (state->csc_mask & SS_DETECT) { 533 reg |= I365_CSC_DETECT; 534 } 535 if (state->flags & SS_IOCARD) { 536 if (state->csc_mask & SS_STSCHG) 537 reg |= I365_CSC_STSCHG; 538 } else { 539 if (state->csc_mask & SS_BATDEAD) 540 reg |= I365_CSC_BVD1; 541 if (state->csc_mask & SS_BATWARN) 542 reg |= I365_CSC_BVD2; 543 if (state->csc_mask & SS_READY) 544 reg |= I365_CSC_READY; 545 546 } 547 548 /* now write the value and clear the (probably bogus) pending stuff by doing a dummy read*/ 549 550 indirect_write(sock,I365_CSCINT,reg); 551 (void)indirect_read(sock,I365_CSC); 552 553 leave("i82092aa_set_socket"); 554 return 0; 555} 556 557static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_map *io) 558{ 559 unsigned int sock = container_of(socket, struct socket_info, socket)->number; 560 unsigned char map, ioctl; 561 562 enter("i82092aa_set_io_map"); 563 564 map = io->map; 565 566 /* Check error conditions */ 567 if (map > 1) { 568 leave("i82092aa_set_io_map with invalid map"); 569 return -EINVAL; 570 } 571 if ((io->start > 0xffff) || (io->stop > 0xffff) || (io->stop < io->start)){ 572 leave("i82092aa_set_io_map with invalid io"); 573 return -EINVAL; 574 } 575 576 /* Turn off the window before changing anything */ 577 if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_IO(map)) 578 indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_IO(map)); 579 580/* printk("set_io_map: Setting range to %x - %x \n",io->start,io->stop); */ 581 582 /* write the new values */ 583 indirect_write16(sock,I365_IO(map)+I365_W_START,io->start); 584 indirect_write16(sock,I365_IO(map)+I365_W_STOP,io->stop); 585 586 ioctl = indirect_read(sock,I365_IOCTL) & ~I365_IOCTL_MASK(map); 587 588 if (io->flags & (MAP_16BIT|MAP_AUTOSZ)) 589 ioctl |= I365_IOCTL_16BIT(map); 590 591 indirect_write(sock,I365_IOCTL,ioctl); 592 593 /* Turn the window back on if needed */ 594 if (io->flags & MAP_ACTIVE) 595 indirect_setbit(sock,I365_ADDRWIN,I365_ENA_IO(map)); 596 597 leave("i82092aa_set_io_map"); 598 return 0; 599} 600 601static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem) 602{ 603 struct socket_info *sock_info = container_of(socket, struct socket_info, socket); 604 unsigned int sock = sock_info->number; 605 struct pci_bus_region region; 606 unsigned short base, i; 607 unsigned char map; 608 609 enter("i82092aa_set_mem_map"); 610 611 pcibios_resource_to_bus(sock_info->dev->bus, ®ion, mem->res); 612 613 map = mem->map; 614 if (map > 4) { 615 leave("i82092aa_set_mem_map: invalid map"); 616 return -EINVAL; 617 } 618 619 620 if ( (mem->card_start > 0x3ffffff) || (region.start > region.end) || 621 (mem->speed > 1000) ) { 622 leave("i82092aa_set_mem_map: invalid address / speed"); 623 printk("invalid mem map for socket %i: %llx to %llx with a " 624 "start of %x\n", 625 sock, 626 (unsigned long long)region.start, 627 (unsigned long long)region.end, 628 mem->card_start); 629 return -EINVAL; 630 } 631 632 /* Turn off the window before changing anything */ 633 if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_MEM(map)) 634 indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_MEM(map)); 635 636 637/* printk("set_mem_map: Setting map %i range to %x - %x on socket %i, speed is %i, active = %i \n",map, region.start,region.end,sock,mem->speed,mem->flags & MAP_ACTIVE); */ 638 639 /* write the start address */ 640 base = I365_MEM(map); 641 i = (region.start >> 12) & 0x0fff; 642 if (mem->flags & MAP_16BIT) 643 i |= I365_MEM_16BIT; 644 if (mem->flags & MAP_0WS) 645 i |= I365_MEM_0WS; 646 indirect_write16(sock,base+I365_W_START,i); 647 648 /* write the stop address */ 649 650 i= (region.end >> 12) & 0x0fff; 651 switch (to_cycles(mem->speed)) { 652 case 0: 653 break; 654 case 1: 655 i |= I365_MEM_WS0; 656 break; 657 case 2: 658 i |= I365_MEM_WS1; 659 break; 660 default: 661 i |= I365_MEM_WS1 | I365_MEM_WS0; 662 break; 663 } 664 665 indirect_write16(sock,base+I365_W_STOP,i); 666 667 /* card start */ 668 669 i = ((mem->card_start - region.start) >> 12) & 0x3fff; 670 if (mem->flags & MAP_WRPROT) 671 i |= I365_MEM_WRPROT; 672 if (mem->flags & MAP_ATTRIB) { 673/* printk("requesting attribute memory for socket %i\n",sock);*/ 674 i |= I365_MEM_REG; 675 } else { 676/* printk("requesting normal memory for socket %i\n",sock);*/ 677 } 678 indirect_write16(sock,base+I365_W_OFF,i); 679 680 /* Enable the window if necessary */ 681 if (mem->flags & MAP_ACTIVE) 682 indirect_setbit(sock, I365_ADDRWIN, I365_ENA_MEM(map)); 683 684 leave("i82092aa_set_mem_map"); 685 return 0; 686} 687 688static int i82092aa_module_init(void) 689{ 690 return pci_register_driver(&i82092aa_pci_driver); 691} 692 693static void i82092aa_module_exit(void) 694{ 695 enter("i82092aa_module_exit"); 696 pci_unregister_driver(&i82092aa_pci_driver); 697 if (sockets[0].io_base>0) 698 release_region(sockets[0].io_base, 2); 699 leave("i82092aa_module_exit"); 700} 701 702module_init(i82092aa_module_init); 703module_exit(i82092aa_module_exit); 704 705