Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.21 771 lines 17 kB view raw
1/* 2 * drivers/pcmcia/m32r_pcc.c 3 * 4 * Device driver for the PCMCIA functionality of M32R. 5 * 6 * Copyright (c) 2001, 2002, 2003, 2004 7 * Hiroyuki Kondo, Naoto Sugai, Hayato Fujiwara 8 */ 9 10#include <linux/module.h> 11#include <linux/moduleparam.h> 12#include <linux/init.h> 13#include <linux/types.h> 14#include <linux/fcntl.h> 15#include <linux/string.h> 16#include <linux/kernel.h> 17#include <linux/errno.h> 18#include <linux/timer.h> 19#include <linux/slab.h> 20#include <linux/ioport.h> 21#include <linux/delay.h> 22#include <linux/workqueue.h> 23#include <linux/interrupt.h> 24#include <linux/platform_device.h> 25#include <asm/irq.h> 26#include <asm/io.h> 27#include <asm/bitops.h> 28#include <asm/system.h> 29#include <asm/addrspace.h> 30 31#include <pcmcia/cs_types.h> 32#include <pcmcia/ss.h> 33#include <pcmcia/cs.h> 34 35/* XXX: should be moved into asm/irq.h */ 36#define PCC0_IRQ 24 37#define PCC1_IRQ 25 38 39#include "m32r_pcc.h" 40 41#define CHAOS_PCC_DEBUG 42#ifdef CHAOS_PCC_DEBUG 43 static volatile u_short dummy_readbuf; 44#endif 45 46#define PCC_DEBUG_DBEX 47 48#ifdef DEBUG 49static int m32r_pcc_debug; 50module_param(m32r_pcc_debug, int, 0644); 51#define debug(lvl, fmt, arg...) do { \ 52 if (m32r_pcc_debug > (lvl)) \ 53 printk(KERN_DEBUG "m32r_pcc: " fmt , ## arg); \ 54} while (0) 55#else 56#define debug(n, args...) do { } while (0) 57#endif 58 59/* Poll status interval -- 0 means default to interrupt */ 60static int poll_interval = 0; 61 62typedef enum pcc_space { as_none = 0, as_comm, as_attr, as_io } pcc_as_t; 63 64typedef struct pcc_socket { 65 u_short type, flags; 66 struct pcmcia_socket socket; 67 unsigned int number; 68 kio_addr_t ioaddr; 69 u_long mapaddr; 70 u_long base; /* PCC register base */ 71 u_char cs_irq, intr; 72 pccard_io_map io_map[MAX_IO_WIN]; 73 pccard_mem_map mem_map[MAX_WIN]; 74 u_char io_win; 75 u_char mem_win; 76 pcc_as_t current_space; 77 u_char last_iodbex; 78#ifdef CHAOS_PCC_DEBUG 79 u_char last_iosize; 80#endif 81#ifdef CONFIG_PROC_FS 82 struct proc_dir_entry *proc; 83#endif 84} pcc_socket_t; 85 86static int pcc_sockets = 0; 87static pcc_socket_t socket[M32R_MAX_PCC] = { 88 { 0, }, /* ... */ 89}; 90 91/*====================================================================*/ 92 93static unsigned int pcc_get(u_short, unsigned int); 94static void pcc_set(u_short, unsigned int , unsigned int ); 95 96static DEFINE_SPINLOCK(pcc_lock); 97 98void pcc_iorw(int sock, unsigned long port, void *buf, size_t size, size_t nmemb, int wr, int flag) 99{ 100 u_long addr; 101 u_long flags; 102 int need_ex; 103#ifdef PCC_DEBUG_DBEX 104 int _dbex; 105#endif 106 pcc_socket_t *t = &socket[sock]; 107#ifdef CHAOS_PCC_DEBUG 108 int map_changed = 0; 109#endif 110 111 /* Need lock ? */ 112 spin_lock_irqsave(&pcc_lock, flags); 113 114 /* 115 * Check if need dbex 116 */ 117 need_ex = (size > 1 && flag == 0) ? PCMOD_DBEX : 0; 118#ifdef PCC_DEBUG_DBEX 119 _dbex = need_ex; 120 need_ex = 0; 121#endif 122 123 /* 124 * calculate access address 125 */ 126 addr = t->mapaddr + port - t->ioaddr + KSEG1; /* XXX */ 127 128 /* 129 * Check current mapping 130 */ 131 if (t->current_space != as_io || t->last_iodbex != need_ex) { 132 133 u_long cbsz; 134 135 /* 136 * Disable first 137 */ 138 pcc_set(sock, PCCR, 0); 139 140 /* 141 * Set mode and io address 142 */ 143 cbsz = (t->flags & MAP_16BIT) ? 0 : PCMOD_CBSZ; 144 pcc_set(sock, PCMOD, PCMOD_AS_IO | cbsz | need_ex); 145 pcc_set(sock, PCADR, addr & 0x1ff00000); 146 147 /* 148 * Enable and read it 149 */ 150 pcc_set(sock, PCCR, 1); 151 152#ifdef CHAOS_PCC_DEBUG 153#if 0 154 map_changed = (t->current_space == as_attr && size == 2); /* XXX */ 155#else 156 map_changed = 1; 157#endif 158#endif 159 t->current_space = as_io; 160 } 161 162 /* 163 * access to IO space 164 */ 165 if (size == 1) { 166 /* Byte */ 167 unsigned char *bp = (unsigned char *)buf; 168 169#ifdef CHAOS_DEBUG 170 if (map_changed) { 171 dummy_readbuf = readb(addr); 172 } 173#endif 174 if (wr) { 175 /* write Byte */ 176 while (nmemb--) { 177 writeb(*bp++, addr); 178 } 179 } else { 180 /* read Byte */ 181 while (nmemb--) { 182 *bp++ = readb(addr); 183 } 184 } 185 } else { 186 /* Word */ 187 unsigned short *bp = (unsigned short *)buf; 188 189#ifdef CHAOS_PCC_DEBUG 190 if (map_changed) { 191 dummy_readbuf = readw(addr); 192 } 193#endif 194 if (wr) { 195 /* write Word */ 196 while (nmemb--) { 197#ifdef PCC_DEBUG_DBEX 198 if (_dbex) { 199 unsigned char *cp = (unsigned char *)bp; 200 unsigned short tmp; 201 tmp = cp[1] << 8 | cp[0]; 202 writew(tmp, addr); 203 bp++; 204 } else 205#endif 206 writew(*bp++, addr); 207 } 208 } else { 209 /* read Word */ 210 while (nmemb--) { 211#ifdef PCC_DEBUG_DBEX 212 if (_dbex) { 213 unsigned char *cp = (unsigned char *)bp; 214 unsigned short tmp; 215 tmp = readw(addr); 216 cp[0] = tmp & 0xff; 217 cp[1] = (tmp >> 8) & 0xff; 218 bp++; 219 } else 220#endif 221 *bp++ = readw(addr); 222 } 223 } 224 } 225 226#if 1 227 /* addr is no longer used */ 228 if ((addr = pcc_get(sock, PCIRC)) & PCIRC_BWERR) { 229 printk("m32r_pcc: BWERR detected : port 0x%04lx : iosize %dbit\n", 230 port, size * 8); 231 pcc_set(sock, PCIRC, addr); 232 } 233#endif 234 /* 235 * save state 236 */ 237 t->last_iosize = size; 238 t->last_iodbex = need_ex; 239 240 /* Need lock ? */ 241 242 spin_unlock_irqrestore(&pcc_lock,flags); 243 244 return; 245} 246 247void pcc_ioread(int sock, unsigned long port, void *buf, size_t size, size_t nmemb, int flag) { 248 pcc_iorw(sock, port, buf, size, nmemb, 0, flag); 249} 250 251void pcc_iowrite(int sock, unsigned long port, void *buf, size_t size, size_t nmemb, int flag) { 252 pcc_iorw(sock, port, buf, size, nmemb, 1, flag); 253} 254 255/*====================================================================*/ 256 257#define IS_REGISTERED 0x2000 258#define IS_ALIVE 0x8000 259 260typedef struct pcc_t { 261 char *name; 262 u_short flags; 263} pcc_t; 264 265static pcc_t pcc[] = { 266 { "xnux2", 0 }, { "xnux2", 0 }, 267}; 268 269static irqreturn_t pcc_interrupt(int, void *); 270 271/*====================================================================*/ 272 273static struct timer_list poll_timer; 274 275static unsigned int pcc_get(u_short sock, unsigned int reg) 276{ 277 return inl(socket[sock].base + reg); 278} 279 280 281static void pcc_set(u_short sock, unsigned int reg, unsigned int data) 282{ 283 outl(data, socket[sock].base + reg); 284} 285 286/*====================================================================== 287 288 See if a card is present, powered up, in IO mode, and already 289 bound to a (non PC Card) Linux driver. We leave these alone. 290 291 We make an exception for cards that seem to be serial devices. 292 293======================================================================*/ 294 295static int __init is_alive(u_short sock) 296{ 297 unsigned int stat; 298 unsigned int f; 299 300 stat = pcc_get(sock, PCIRC); 301 f = (stat & (PCIRC_CDIN1 | PCIRC_CDIN2)) >> 16; 302 if(!f){ 303 printk("m32r_pcc: No Card is detected at socket %d : stat = 0x%08x\n",stat,sock); 304 return 0; 305 } 306 if(f!=3) 307 printk("m32r_pcc: Insertion fail (%.8x) at socket %d\n",stat,sock); 308 else 309 printk("m32r_pcc: Card is Inserted at socket %d(%.8x)\n",sock,stat); 310 return 0; 311} 312 313static void add_pcc_socket(ulong base, int irq, ulong mapaddr, kio_addr_t ioaddr) 314{ 315 pcc_socket_t *t = &socket[pcc_sockets]; 316 317 /* add sockets */ 318 t->ioaddr = ioaddr; 319 t->mapaddr = mapaddr; 320 t->base = base; 321#ifdef CHAOS_PCC_DEBUG 322 t->flags = MAP_16BIT; 323#else 324 t->flags = 0; 325#endif 326 if (is_alive(pcc_sockets)) 327 t->flags |= IS_ALIVE; 328 329 /* add pcc */ 330 if (t->base > 0) { 331 request_region(t->base, 0x20, "m32r-pcc"); 332 } 333 334 printk(KERN_INFO " %s ", pcc[pcc_sockets].name); 335 printk("pcc at 0x%08lx\n", t->base); 336 337 /* Update socket interrupt information, capabilities */ 338 t->socket.features |= (SS_CAP_PCCARD | SS_CAP_STATIC_MAP); 339 t->socket.map_size = M32R_PCC_MAPSIZE; 340 t->socket.io_offset = ioaddr; /* use for io access offset */ 341 t->socket.irq_mask = 0; 342 t->socket.pci_irq = 2 + pcc_sockets; /* XXX */ 343 344 request_irq(irq, pcc_interrupt, 0, "m32r-pcc", pcc_interrupt); 345 346 pcc_sockets++; 347 348 return; 349} 350 351 352/*====================================================================*/ 353 354static irqreturn_t pcc_interrupt(int irq, void *dev) 355{ 356 int i, j, irc; 357 u_int events, active; 358 int handled = 0; 359 360 debug(4, "m32r: pcc_interrupt(%d)\n", irq); 361 362 for (j = 0; j < 20; j++) { 363 active = 0; 364 for (i = 0; i < pcc_sockets; i++) { 365 if ((socket[i].cs_irq != irq) && 366 (socket[i].socket.pci_irq != irq)) 367 continue; 368 handled = 1; 369 irc = pcc_get(i, PCIRC); 370 irc >>=16; 371 debug(2, "m32r-pcc:interrput: socket %d pcirc 0x%02x ", i, irc); 372 if (!irc) 373 continue; 374 375 events = (irc) ? SS_DETECT : 0; 376 events |= (pcc_get(i,PCCR) & PCCR_PCEN) ? SS_READY : 0; 377 debug(2, " event 0x%02x\n", events); 378 379 if (events) 380 pcmcia_parse_events(&socket[i].socket, events); 381 382 active |= events; 383 active = 0; 384 } 385 if (!active) break; 386 } 387 if (j == 20) 388 printk(KERN_NOTICE "m32r-pcc: infinite loop in interrupt handler\n"); 389 390 debug(4, "m32r-pcc: interrupt done\n"); 391 392 return IRQ_RETVAL(handled); 393} /* pcc_interrupt */ 394 395static void pcc_interrupt_wrapper(u_long data) 396{ 397 pcc_interrupt(0, NULL); 398 init_timer(&poll_timer); 399 poll_timer.expires = jiffies + poll_interval; 400 add_timer(&poll_timer); 401} 402 403/*====================================================================*/ 404 405static int _pcc_get_status(u_short sock, u_int *value) 406{ 407 u_int status; 408 409 status = pcc_get(sock,PCIRC); 410 *value = ((status & PCIRC_CDIN1) && (status & PCIRC_CDIN2)) 411 ? SS_DETECT : 0; 412 413 status = pcc_get(sock,PCCR); 414 415#if 0 416 *value |= (status & PCCR_PCEN) ? SS_READY : 0; 417#else 418 *value |= SS_READY; /* XXX: always */ 419#endif 420 421 status = pcc_get(sock,PCCSIGCR); 422 *value |= (status & PCCSIGCR_VEN) ? SS_POWERON : 0; 423 424 debug(3, "m32r-pcc: GetStatus(%d) = %#4.4x\n", sock, *value); 425 return 0; 426} /* _get_status */ 427 428/*====================================================================*/ 429 430static int _pcc_set_socket(u_short sock, socket_state_t *state) 431{ 432 u_long reg = 0; 433 434 debug(3, "m32r-pcc: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " 435 "io_irq %d, csc_mask %#2.2x)", sock, state->flags, 436 state->Vcc, state->Vpp, state->io_irq, state->csc_mask); 437 438 if (state->Vcc) { 439 /* 440 * 5V only 441 */ 442 if (state->Vcc == 50) { 443 reg |= PCCSIGCR_VEN; 444 } else { 445 return -EINVAL; 446 } 447 } 448 449 if (state->flags & SS_RESET) { 450 debug(3, ":RESET\n"); 451 reg |= PCCSIGCR_CRST; 452 } 453 if (state->flags & SS_OUTPUT_ENA){ 454 debug(3, ":OUTPUT_ENA\n"); 455 /* bit clear */ 456 } else { 457 reg |= PCCSIGCR_SEN; 458 } 459 460 pcc_set(sock,PCCSIGCR,reg); 461 462#ifdef DEBUG 463 if(state->flags & SS_IOCARD){ 464 debug(3, ":IOCARD"); 465 } 466 if (state->flags & SS_PWR_AUTO) { 467 debug(3, ":PWR_AUTO"); 468 } 469 if (state->csc_mask & SS_DETECT) 470 debug(3, ":csc-SS_DETECT"); 471 if (state->flags & SS_IOCARD) { 472 if (state->csc_mask & SS_STSCHG) 473 debug(3, ":STSCHG"); 474 } else { 475 if (state->csc_mask & SS_BATDEAD) 476 debug(3, ":BATDEAD"); 477 if (state->csc_mask & SS_BATWARN) 478 debug(3, ":BATWARN"); 479 if (state->csc_mask & SS_READY) 480 debug(3, ":READY"); 481 } 482 debug(3, "\n"); 483#endif 484 return 0; 485} /* _set_socket */ 486 487/*====================================================================*/ 488 489static int _pcc_set_io_map(u_short sock, struct pccard_io_map *io) 490{ 491 u_char map; 492 493 debug(3, "m32r-pcc: SetIOMap(%d, %d, %#2.2x, %d ns, " 494 "%#lx-%#lx)\n", sock, io->map, io->flags, 495 io->speed, io->start, io->stop); 496 map = io->map; 497 498 return 0; 499} /* _set_io_map */ 500 501/*====================================================================*/ 502 503static int _pcc_set_mem_map(u_short sock, struct pccard_mem_map *mem) 504{ 505 506 u_char map = mem->map; 507 u_long mode; 508 u_long addr; 509 pcc_socket_t *t = &socket[sock]; 510#ifdef CHAOS_PCC_DEBUG 511#if 0 512 pcc_as_t last = t->current_space; 513#endif 514#endif 515 516 debug(3, "m32r-pcc: SetMemMap(%d, %d, %#2.2x, %d ns, " 517 "%#lx, %#x)\n", sock, map, mem->flags, 518 mem->speed, mem->static_start, mem->card_start); 519 520 /* 521 * sanity check 522 */ 523 if ((map > MAX_WIN) || (mem->card_start > 0x3ffffff)){ 524 return -EINVAL; 525 } 526 527 /* 528 * de-activate 529 */ 530 if ((mem->flags & MAP_ACTIVE) == 0) { 531 t->current_space = as_none; 532 return 0; 533 } 534 535 /* 536 * Disable first 537 */ 538 pcc_set(sock, PCCR, 0); 539 540 /* 541 * Set mode 542 */ 543 if (mem->flags & MAP_ATTRIB) { 544 mode = PCMOD_AS_ATTRIB | PCMOD_CBSZ; 545 t->current_space = as_attr; 546 } else { 547 mode = 0; /* common memory */ 548 t->current_space = as_comm; 549 } 550 pcc_set(sock, PCMOD, mode); 551 552 /* 553 * Set address 554 */ 555 addr = t->mapaddr + (mem->card_start & M32R_PCC_MAPMASK); 556 pcc_set(sock, PCADR, addr); 557 558 mem->static_start = addr + mem->card_start; 559 560 /* 561 * Enable again 562 */ 563 pcc_set(sock, PCCR, 1); 564 565#ifdef CHAOS_PCC_DEBUG 566#if 0 567 if (last != as_attr) { 568#else 569 if (1) { 570#endif 571 dummy_readbuf = *(u_char *)(addr + KSEG1); 572 } 573#endif 574 575 return 0; 576 577} /* _set_mem_map */ 578 579#if 0 /* driver model ordering issue */ 580/*====================================================================== 581 582 Routines for accessing socket information and register dumps via 583 /proc/bus/pccard/... 584 585======================================================================*/ 586 587static ssize_t show_info(struct class_device *class_dev, char *buf) 588{ 589 pcc_socket_t *s = container_of(class_dev, struct pcc_socket, 590 socket.dev); 591 592 return sprintf(buf, "type: %s\nbase addr: 0x%08lx\n", 593 pcc[s->type].name, s->base); 594} 595 596static ssize_t show_exca(struct class_device *class_dev, char *buf) 597{ 598 /* FIXME */ 599 600 return 0; 601} 602 603static CLASS_DEVICE_ATTR(info, S_IRUGO, show_info, NULL); 604static CLASS_DEVICE_ATTR(exca, S_IRUGO, show_exca, NULL); 605#endif 606 607/*====================================================================*/ 608 609/* this is horribly ugly... proper locking needs to be done here at 610 * some time... */ 611#define LOCKED(x) do { \ 612 int retval; \ 613 unsigned long flags; \ 614 spin_lock_irqsave(&pcc_lock, flags); \ 615 retval = x; \ 616 spin_unlock_irqrestore(&pcc_lock, flags); \ 617 return retval; \ 618} while (0) 619 620 621static int pcc_get_status(struct pcmcia_socket *s, u_int *value) 622{ 623 unsigned int sock = container_of(s, struct pcc_socket, socket)->number; 624 625 if (socket[sock].flags & IS_ALIVE) { 626 *value = 0; 627 return -EINVAL; 628 } 629 LOCKED(_pcc_get_status(sock, value)); 630} 631 632static int pcc_set_socket(struct pcmcia_socket *s, socket_state_t *state) 633{ 634 unsigned int sock = container_of(s, struct pcc_socket, socket)->number; 635 636 if (socket[sock].flags & IS_ALIVE) 637 return -EINVAL; 638 639 LOCKED(_pcc_set_socket(sock, state)); 640} 641 642static int pcc_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io) 643{ 644 unsigned int sock = container_of(s, struct pcc_socket, socket)->number; 645 646 if (socket[sock].flags & IS_ALIVE) 647 return -EINVAL; 648 LOCKED(_pcc_set_io_map(sock, io)); 649} 650 651static int pcc_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem) 652{ 653 unsigned int sock = container_of(s, struct pcc_socket, socket)->number; 654 655 if (socket[sock].flags & IS_ALIVE) 656 return -EINVAL; 657 LOCKED(_pcc_set_mem_map(sock, mem)); 658} 659 660static int pcc_init(struct pcmcia_socket *s) 661{ 662 debug(4, "m32r-pcc: init call\n"); 663 return 0; 664} 665 666static struct pccard_operations pcc_operations = { 667 .init = pcc_init, 668 .get_status = pcc_get_status, 669 .set_socket = pcc_set_socket, 670 .set_io_map = pcc_set_io_map, 671 .set_mem_map = pcc_set_mem_map, 672}; 673 674/*====================================================================*/ 675 676static struct device_driver pcc_driver = { 677 .name = "pcc", 678 .bus = &platform_bus_type, 679 .suspend = pcmcia_socket_dev_suspend, 680 .resume = pcmcia_socket_dev_resume, 681}; 682 683static struct platform_device pcc_device = { 684 .name = "pcc", 685 .id = 0, 686}; 687 688/*====================================================================*/ 689 690static int __init init_m32r_pcc(void) 691{ 692 int i, ret; 693 694 ret = driver_register(&pcc_driver); 695 if (ret) 696 return ret; 697 698 ret = platform_device_register(&pcc_device); 699 if (ret){ 700 driver_unregister(&pcc_driver); 701 return ret; 702 } 703 704 printk(KERN_INFO "m32r PCC probe:\n"); 705 706 pcc_sockets = 0; 707 708 add_pcc_socket(M32R_PCC0_BASE, PCC0_IRQ, M32R_PCC0_MAPBASE, 0x1000); 709 710#ifdef CONFIG_M32RPCC_SLOT2 711 add_pcc_socket(M32R_PCC1_BASE, PCC1_IRQ, M32R_PCC1_MAPBASE, 0x2000); 712#endif 713 714 if (pcc_sockets == 0) { 715 printk("socket is not found.\n"); 716 platform_device_unregister(&pcc_device); 717 driver_unregister(&pcc_driver); 718 return -ENODEV; 719 } 720 721 /* Set up interrupt handler(s) */ 722 723 for (i = 0 ; i < pcc_sockets ; i++) { 724 socket[i].socket.dev.parent = &pcc_device.dev; 725 socket[i].socket.ops = &pcc_operations; 726 socket[i].socket.resource_ops = &pccard_static_ops; 727 socket[i].socket.owner = THIS_MODULE; 728 socket[i].number = i; 729 ret = pcmcia_register_socket(&socket[i].socket); 730 if (!ret) 731 socket[i].flags |= IS_REGISTERED; 732 733#if 0 /* driver model ordering issue */ 734 class_device_create_file(&socket[i].socket.dev, 735 &class_device_attr_info); 736 class_device_create_file(&socket[i].socket.dev, 737 &class_device_attr_exca); 738#endif 739 } 740 741 /* Finally, schedule a polling interrupt */ 742 if (poll_interval != 0) { 743 poll_timer.function = pcc_interrupt_wrapper; 744 poll_timer.data = 0; 745 init_timer(&poll_timer); 746 poll_timer.expires = jiffies + poll_interval; 747 add_timer(&poll_timer); 748 } 749 750 return 0; 751} /* init_m32r_pcc */ 752 753static void __exit exit_m32r_pcc(void) 754{ 755 int i; 756 757 for (i = 0; i < pcc_sockets; i++) 758 if (socket[i].flags & IS_REGISTERED) 759 pcmcia_unregister_socket(&socket[i].socket); 760 761 platform_device_unregister(&pcc_device); 762 if (poll_interval != 0) 763 del_timer_sync(&poll_timer); 764 765 driver_unregister(&pcc_driver); 766} /* exit_m32r_pcc */ 767 768module_init(init_m32r_pcc); 769module_exit(exit_m32r_pcc); 770MODULE_LICENSE("Dual MPL/GPL"); 771/*====================================================================*/