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