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

[POWERPC] 8xx: mpc885ads pcmcia support

Adds support for PowerQuicc on-chip PCMCIA. The driver is implemented as
of_device, so only arch/powerpc stuff is capable to use it, which now implies
only mpc885ads reference board.

To cope with the code that should be hooked inside driver, but is really board
specific (like set_voltage), global structure mpc8xx_pcmcia_ops holds
necessary function pointers that are filled in the BSP code.

[akpm@linux-foundation.org: whitespace diddles]
Signed-off-by: Vitaly Bordug <vitb@kernel.crashing.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Olof Johansson <olof@lixom.net>
Cc: Dominik Brodowski <linux@dominikbrodowski.net>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>

authored by

Vitaly Bordug and committed by
Kumar Gala
80128ff7 90faf4fa

+294 -194
+11
arch/powerpc/boot/dts/mpc885ads.dts
··· 112 112 compatible = "CPM"; 113 113 }; 114 114 115 + pcmcia@0080 { 116 + #address-cells = <3>; 117 + #interrupt-cells = <1>; 118 + #size-cells = <2>; 119 + compatible = "fsl,pq-pcmcia"; 120 + device_type = "pcmcia"; 121 + reg = <80 80>; 122 + interrupt-parent = <ff000000>; 123 + interrupts = <d 1>; 124 + }; 125 + 115 126 cpm@ff000000 { 116 127 linux,phandle = <ff000000>; 117 128 #address-cells = <1>;
+5
arch/powerpc/platforms/8xx/m8xx_setup.c
··· 32 32 #include <linux/root_dev.h> 33 33 #include <linux/time.h> 34 34 #include <linux/rtc.h> 35 + #include <linux/fsl_devices.h> 35 36 36 37 #include <asm/mmu.h> 37 38 #include <asm/reg.h> ··· 49 48 #include <mm/mmu_decl.h> 50 49 51 50 #include "sysdev/mpc8xx_pic.h" 51 + 52 + #ifdef CONFIG_PCMCIA_M8XX 53 + struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops; 54 + #endif 52 55 53 56 void m8xx_calibrate_decr(void); 54 57 extern void m8xx_wdt_handler_install(bd_t *bp);
+71
arch/powerpc/platforms/8xx/mpc885ads_setup.c
··· 22 22 23 23 #include <linux/fs_enet_pd.h> 24 24 #include <linux/fs_uart_pd.h> 25 + #include <linux/fsl_devices.h> 25 26 #include <linux/mii.h> 26 27 27 28 #include <asm/delay.h> ··· 51 50 static void init_smc1_uart_ioports(struct fs_uart_platform_info* fpi); 52 51 static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi); 53 52 static void init_scc3_ioports(struct fs_platform_info* ptr); 53 + 54 + #ifdef CONFIG_PCMCIA_M8XX 55 + static void pcmcia_hw_setup(int slot, int enable) 56 + { 57 + unsigned *bcsr_io; 58 + 59 + bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); 60 + if (enable) 61 + clrbits32(bcsr_io, BCSR1_PCCEN); 62 + else 63 + setbits32(bcsr_io, BCSR1_PCCEN); 64 + 65 + iounmap(bcsr_io); 66 + } 67 + 68 + static int pcmcia_set_voltage(int slot, int vcc, int vpp) 69 + { 70 + u32 reg = 0; 71 + unsigned *bcsr_io; 72 + 73 + bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); 74 + 75 + switch(vcc) { 76 + case 0: 77 + break; 78 + case 33: 79 + reg |= BCSR1_PCCVCC0; 80 + break; 81 + case 50: 82 + reg |= BCSR1_PCCVCC1; 83 + break; 84 + default: 85 + return 1; 86 + } 87 + 88 + switch(vpp) { 89 + case 0: 90 + break; 91 + case 33: 92 + case 50: 93 + if(vcc == vpp) 94 + reg |= BCSR1_PCCVPP1; 95 + else 96 + return 1; 97 + break; 98 + case 120: 99 + if ((vcc == 33) || (vcc == 50)) 100 + reg |= BCSR1_PCCVPP0; 101 + else 102 + return 1; 103 + default: 104 + return 1; 105 + } 106 + 107 + /* first, turn off all power */ 108 + clrbits32(bcsr_io, 0x00610000); 109 + 110 + /* enable new powersettings */ 111 + setbits32(bcsr_io, reg); 112 + 113 + iounmap(bcsr_io); 114 + return 0; 115 + } 116 + #endif 54 117 55 118 void __init mpc885ads_board_setup(void) 56 119 { ··· 179 114 iounmap(bcsr_io); 180 115 immr_unmap(io_port); 181 116 117 + #endif 118 + 119 + #ifdef CONFIG_PCMCIA_M8XX 120 + /*Set up board specific hook-ups*/ 121 + m8xx_pcmcia_ops.hw_ctrl = pcmcia_hw_setup; 122 + m8xx_pcmcia_ops.voltage_set = pcmcia_set_voltage; 182 123 #endif 183 124 } 184 125
+13
arch/powerpc/sysdev/fsl_soc.c
··· 1028 1028 1029 1029 arch_initcall(fs_enet_of_init); 1030 1030 1031 + static int __init fsl_pcmcia_of_init(void) 1032 + { 1033 + struct device_node *np = NULL; 1034 + /* 1035 + * Register all the devices which type is "pcmcia" 1036 + */ 1037 + while ((np = of_find_compatible_node(np, 1038 + "pcmcia", "fsl,pq-pcmcia")) != NULL) 1039 + of_platform_device_create(np, "m8xx-pcmcia", NULL); 1040 + return 0; 1041 + } 1042 + 1043 + arch_initcall(fsl_pcmcia_of_init); 1031 1044 1032 1045 static const char *smc_regs = "regs"; 1033 1046 static const char *smc_pram = "pram";
+9 -2
arch/powerpc/sysdev/mpc8xx_pic.h
··· 4 4 #include <linux/irq.h> 5 5 #include <linux/interrupt.h> 6 6 7 - extern struct hw_interrupt_type mpc8xx_pic; 8 - 9 7 int mpc8xx_pic_init(void); 10 8 unsigned int mpc8xx_get_irq(void); 9 + 10 + /* 11 + * Some internal interrupt registers use an 8-bit mask for the interrupt 12 + * level instead of a number. 13 + */ 14 + static inline uint mk_int_int_mask(uint mask) 15 + { 16 + return (1 << (7 - (mask/2))); 17 + } 11 18 12 19 #endif /* _PPC_KERNEL_PPC8xx_H */
+8 -7
drivers/pcmcia/Kconfig
··· 180 180 PCMCIA cards are plugged into. If unsure, say N. 181 181 182 182 config PCMCIA_M8XX 183 - tristate "MPC8xx PCMCIA support" 184 - depends on PCMCIA && PPC && 8xx 185 - select PCCARD_IODYN 186 - help 187 - Say Y here to include support for PowerPC 8xx series PCMCIA 188 - controller. 183 + tristate "MPC8xx PCMCIA support" 184 + depends on PCMCIA && PPC && 8xx 185 + select PCCARD_IODYN 186 + select PCCARD_NONSTATIC 187 + help 188 + Say Y here to include support for PowerPC 8xx series PCMCIA 189 + controller. 189 190 190 - This driver is also available as a module called m8xx_pcmcia. 191 + This driver is also available as a module called m8xx_pcmcia. 191 192 192 193 config HD64465_PCMCIA 193 194 tristate "HD64465 host bridge support"
+168 -185
drivers/pcmcia/m8xx_pcmcia.c
··· 10 10 * Further fixes, v2.6 kernel port 11 11 * <marcelo.tosatti@cyclades.com> 12 12 * 13 - * Some fixes, additions (C) 2005 Montavista Software, Inc. 13 + * Some fixes, additions (C) 2005-2007 Montavista Software, Inc. 14 14 * <vbordug@ru.mvista.com> 15 15 * 16 16 * "The ExCA standard specifies that socket controllers should provide ··· 40 40 #include <linux/fcntl.h> 41 41 #include <linux/string.h> 42 42 43 - #include <asm/io.h> 44 - #include <asm/bitops.h> 45 - #include <asm/system.h> 46 - 47 43 #include <linux/kernel.h> 48 44 #include <linux/errno.h> 49 45 #include <linux/slab.h> ··· 47 51 #include <linux/ioport.h> 48 52 #include <linux/delay.h> 49 53 #include <linux/interrupt.h> 50 - #include <linux/platform_device.h> 54 + #include <linux/fsl_devices.h> 51 55 56 + #include <asm/io.h> 57 + #include <asm/bitops.h> 58 + #include <asm/system.h> 59 + #include <asm/time.h> 52 60 #include <asm/mpc8xx.h> 53 61 #include <asm/8xx_immap.h> 54 62 #include <asm/irq.h> 63 + #include <asm/fs_pd.h> 64 + #include <asm/of_device.h> 65 + #include <asm/of_platform.h> 55 66 56 67 #include <pcmcia/version.h> 57 68 #include <pcmcia/cs_types.h> ··· 149 146 #define PCMCIA_MEM_WIN_BASE 0xe0000000 /* base address for memory window 0 */ 150 147 #define PCMCIA_MEM_WIN_SIZE 0x04000000 /* each memory window is 64 MByte */ 151 148 #define PCMCIA_IO_WIN_BASE _IO_BASE /* base address for io window 0 */ 152 - 153 - #define PCMCIA_SCHLVL PCMCIA_INTERRUPT /* Status Change Interrupt Level */ 154 - 155 149 /* ------------------------------------------------------------------------- */ 156 150 157 - /* 2.4.x and newer has this always in HZ */ 158 - #define M8XX_BUSFREQ ((((bd_t *)&(__res))->bi_busfreq)) 159 - 160 - static int pcmcia_schlvl = PCMCIA_SCHLVL; 151 + static int pcmcia_schlvl; 161 152 162 153 static DEFINE_SPINLOCK(events_lock); 163 - 164 154 165 155 #define PCMCIA_SOCKET_KEY_5V 1 166 156 #define PCMCIA_SOCKET_KEY_LV 2 167 157 168 158 /* look up table for pgcrx registers */ 169 - static u32 *m8xx_pgcrx[2] = { 170 - &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcra, 171 - &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcrb 172 - }; 159 + static u32 *m8xx_pgcrx[2]; 173 160 174 161 /* 175 162 * This structure is used to address each window in the PCMCIA controller. ··· 221 228 u32 eventbit; 222 229 }; 223 230 231 + static const char driver_name[] = "m8xx-pcmcia"; 232 + 224 233 struct socket_info { 225 234 void (*handler)(void *info, u32 events); 226 235 void *info; 227 236 228 237 u32 slot; 238 + pcmconf8xx_t *pcmcia; 239 + u32 bus_freq; 240 + int hwirq; 229 241 230 242 socket_state_t state; 231 243 struct pccard_mem_map mem_win[PCMCIA_MEM_WIN_NO]; ··· 406 408 #if defined(CONFIG_MPC885ADS) 407 409 408 410 #define PCMCIA_BOARD_MSG "MPC885ADS" 409 - 410 - static int voltage_set(int slot, int vcc, int vpp) 411 - { 412 - u32 reg = 0; 413 - unsigned *bcsr_io; 414 - 415 - bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); 416 - 417 - switch(vcc) { 418 - case 0: 419 - break; 420 - case 33: 421 - reg |= BCSR1_PCCVCC0; 422 - break; 423 - case 50: 424 - reg |= BCSR1_PCCVCC1; 425 - break; 426 - default: 427 - goto out_unmap; 428 - } 429 - 430 - switch(vpp) { 431 - case 0: 432 - break; 433 - case 33: 434 - case 50: 435 - if(vcc == vpp) 436 - reg |= BCSR1_PCCVPP1; 437 - else 438 - goto out_unmap; 439 - break; 440 - case 120: 441 - if ((vcc == 33) || (vcc == 50)) 442 - reg |= BCSR1_PCCVPP0; 443 - else 444 - goto out_unmap; 445 - default: 446 - goto out_unmap; 447 - } 448 - 449 - /* first, turn off all power */ 450 - out_be32(bcsr_io, in_be32(bcsr_io) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK)); 451 - 452 - /* enable new powersettings */ 453 - out_be32(bcsr_io, in_be32(bcsr_io) | reg); 454 - 455 - iounmap(bcsr_io); 456 - return 0; 457 - 458 - out_unmap: 459 - iounmap(bcsr_io); 460 - return 1; 461 - } 462 - 463 411 #define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V 464 412 465 - static void hardware_enable(int slot) 413 + static inline void hardware_enable(int slot) 466 414 { 467 - unsigned *bcsr_io; 468 - 469 - bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); 470 - out_be32(bcsr_io, in_be32(bcsr_io) & ~BCSR1_PCCEN); 471 - iounmap(bcsr_io); 415 + m8xx_pcmcia_ops.hw_ctrl(slot, 1); 472 416 } 473 417 474 - static void hardware_disable(int slot) 418 + static inline void hardware_disable(int slot) 475 419 { 476 - unsigned *bcsr_io; 420 + m8xx_pcmcia_ops.hw_ctrl(slot, 0); 421 + } 477 422 478 - bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); 479 - out_be32(bcsr_io, in_be32(bcsr_io) | BCSR1_PCCEN); 480 - iounmap(bcsr_io); 423 + static inline int voltage_set(int slot, int vcc, int vpp) 424 + { 425 + return m8xx_pcmcia_ops.voltage_set(slot, vcc, vpp); 481 426 } 482 427 483 428 #endif ··· 545 604 546 605 #endif /* CONFIG_PRxK */ 547 606 548 - static void m8xx_shutdown(void) 549 - { 550 - u32 m, i; 551 - struct pcmcia_win *w; 552 - 553 - for(i = 0; i < PCMCIA_SOCKETS_NO; i++){ 554 - w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0; 555 - 556 - out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, M8XX_PCMCIA_MASK(i)); 557 - out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) & ~M8XX_PCMCIA_MASK(i)); 558 - 559 - /* turn off interrupt and disable CxOE */ 560 - out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE); 561 - 562 - /* turn off memory windows */ 563 - for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) { 564 - out_be32(&w->or, 0); /* set to not valid */ 565 - w++; 566 - } 567 - 568 - /* turn off voltage */ 569 - voltage_set(i, 0, 0); 570 - 571 - /* disable external hardware */ 572 - hardware_disable(i); 573 - } 574 - 575 - free_irq(pcmcia_schlvl, NULL); 576 - } 577 - 578 - static struct device_driver m8xx_driver = { 579 - .name = "m8xx-pcmcia", 580 - .bus = &platform_bus_type, 581 - .suspend = pcmcia_socket_dev_suspend, 582 - .resume = pcmcia_socket_dev_resume, 583 - }; 584 - 585 - static struct platform_device m8xx_device = { 586 - .name = "m8xx-pcmcia", 587 - .id = 0, 588 - }; 589 - 590 607 static u32 pending_events[PCMCIA_SOCKETS_NO]; 591 608 static DEFINE_SPINLOCK(pending_event_lock); 592 609 ··· 553 654 struct socket_info *s; 554 655 struct event_table *e; 555 656 unsigned int i, events, pscr, pipr, per; 657 + pcmconf8xx_t *pcmcia = socket[0].pcmcia; 556 658 557 659 dprintk("Interrupt!\n"); 558 660 /* get interrupt sources */ 559 661 560 - pscr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr); 561 - pipr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr); 562 - per = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per); 662 + pscr = in_be32(&pcmcia->pcmc_pscr); 663 + pipr = in_be32(&pcmcia->pcmc_pipr); 664 + per = in_be32(&pcmcia->pcmc_per); 563 665 564 666 for(i = 0; i < PCMCIA_SOCKETS_NO; i++) { 565 667 s = &socket[i]; ··· 624 724 per &= ~M8XX_PCMCIA_RDY_L(0); 625 725 per &= ~M8XX_PCMCIA_RDY_L(1); 626 726 627 - out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, per); 727 + out_be32(&pcmcia->pcmc_per, per); 628 728 629 729 if (events) 630 730 pcmcia_parse_events(&socket[i].socket, events); ··· 632 732 } 633 733 634 734 /* clear the interrupt sources */ 635 - out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, pscr); 735 + out_be32(&pcmcia->pcmc_pscr, pscr); 636 736 637 737 dprintk("Interrupt done.\n"); 638 738 ··· 653 753 return k; 654 754 } 655 755 656 - static u32 m8xx_get_speed(u32 ns, u32 is_io) 756 + static u32 m8xx_get_speed(u32 ns, u32 is_io, u32 bus_freq) 657 757 { 658 758 u32 reg, clocks, psst, psl, psht; 659 759 ··· 681 781 682 782 #define ADJ 180 /* 80 % longer accesstime - to be sure */ 683 783 684 - clocks = ((M8XX_BUSFREQ / 1000) * ns) / 1000; 784 + clocks = ((bus_freq / 1000) * ns) / 1000; 685 785 clocks = (clocks * ADJ) / (100*1000); 686 786 if(clocks >= PCMCIA_BMT_LIMIT) { 687 787 printk( "Max access time limit reached\n"); ··· 706 806 int lsock = container_of(sock, struct socket_info, socket)->slot; 707 807 struct socket_info *s = &socket[lsock]; 708 808 unsigned int pipr, reg; 809 + pcmconf8xx_t *pcmcia = s->pcmcia; 709 810 710 - pipr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr); 811 + pipr = in_be32(&pcmcia->pcmc_pipr); 711 812 712 813 *value = ((pipr & (M8XX_PCMCIA_CD1(lsock) 713 814 | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0; ··· 819 918 struct event_table *e; 820 919 unsigned int reg; 821 920 unsigned long flags; 921 + pcmconf8xx_t *pcmcia = socket[0].pcmcia; 822 922 823 923 dprintk( "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " 824 924 "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags, ··· 828 926 /* First, set voltage - bail out if invalid */ 829 927 if(voltage_set(lsock, state->Vcc, state->Vpp)) 830 928 return -EINVAL; 929 + 831 930 832 931 /* Take care of reset... */ 833 932 if(state->flags & SS_RESET) ··· 885 982 * If io_irq is non-zero we should enable irq. 886 983 */ 887 984 if(state->io_irq) { 888 - out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | mk_int_int_mask(state->io_irq) << 24); 985 + out_be32(M8XX_PGCRX(lsock), 986 + in_be32(M8XX_PGCRX(lsock)) | mk_int_int_mask(s->hwirq) << 24); 889 987 /* 890 988 * Strange thing here: 891 989 * The manual does not tell us which interrupt ··· 931 1027 * Writing ones will clear the bits. 932 1028 */ 933 1029 934 - out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, reg); 1030 + out_be32(&pcmcia->pcmc_pscr, reg); 935 1031 936 1032 /* 937 1033 * Write the mask. ··· 940 1036 * Ones will enable the interrupt. 941 1037 */ 942 1038 943 - /* 944 - reg |= ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per 945 - & M8XX_PCMCIA_MASK(lsock); 946 - */ 947 - 948 - reg |= in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) & 949 - (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1)); 950 - 951 - out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, reg); 1039 + reg |= in_be32(&pcmcia->pcmc_per) & (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1)); 1040 + out_be32(&pcmcia->pcmc_per, reg); 952 1041 953 1042 spin_unlock_irqrestore(&events_lock, flags); 954 1043 ··· 959 1062 struct socket_info *s = &socket[lsock]; 960 1063 struct pcmcia_win *w; 961 1064 unsigned int reg, winnr; 1065 + pcmconf8xx_t *pcmcia = s->pcmcia; 1066 + 962 1067 963 1068 #define M8XX_SIZE (io->stop - io->start + 1) 964 1069 #define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start) ··· 985 1086 986 1087 /* setup registers */ 987 1088 988 - w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0; 1089 + w = (void *) &pcmcia->pcmc_pbr0; 989 1090 w += winnr; 990 1091 991 1092 out_be32(&w->or, 0); /* turn off window first */ ··· 994 1095 reg <<= 27; 995 1096 reg |= M8XX_PCMCIA_POR_IO |(lsock << 2); 996 1097 997 - reg |= m8xx_get_speed(io->speed, 1); 1098 + reg |= m8xx_get_speed(io->speed, 1, s->bus_freq); 998 1099 999 1100 if(io->flags & MAP_WRPROT) 1000 1101 reg |= M8XX_PCMCIA_POR_WRPROT; 1001 1102 1002 - if(io->flags & (MAP_16BIT | MAP_AUTOSZ)) 1103 + /*if(io->flags & (MAP_16BIT | MAP_AUTOSZ))*/ 1104 + if(io->flags & MAP_16BIT) 1003 1105 reg |= M8XX_PCMCIA_POR_16BIT; 1004 1106 1005 1107 if(io->flags & MAP_ACTIVE) ··· 1017 1117 1018 1118 /* setup registers */ 1019 1119 1020 - w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0; 1120 + w = (void *) &pcmcia->pcmc_pbr0; 1021 1121 w += winnr; 1022 1122 1023 1123 out_be32(&w->or, 0); /* turn off window */ ··· 1044 1144 struct pcmcia_win *w; 1045 1145 struct pccard_mem_map *old; 1046 1146 unsigned int reg, winnr; 1147 + pcmconf8xx_t *pcmcia = s->pcmcia; 1047 1148 1048 1149 dprintk( "SetMemMap(%d, %d, %#2.2x, %d ns, " 1049 1150 "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags, ··· 1067 1166 1068 1167 /* Setup the window in the pcmcia controller */ 1069 1168 1070 - w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0; 1169 + w = (void *) &pcmcia->pcmc_pbr0; 1071 1170 w += winnr; 1072 1171 1073 1172 reg |= lsock << 2; 1074 1173 1075 - reg |= m8xx_get_speed(mem->speed, 0); 1174 + reg |= m8xx_get_speed(mem->speed, 0, s->bus_freq); 1076 1175 1077 1176 if(mem->flags & MAP_ATTRIB) 1078 1177 reg |= M8XX_PCMCIA_POR_ATTRMEM; ··· 1137 1236 1138 1237 } 1139 1238 1140 - static int m8xx_suspend(struct pcmcia_socket *sock) 1239 + static int m8xx_sock_suspend(struct pcmcia_socket *sock) 1141 1240 { 1142 1241 return m8xx_set_socket(sock, &dead_socket); 1143 1242 } 1144 1243 1145 1244 static struct pccard_operations m8xx_services = { 1146 1245 .init = m8xx_sock_init, 1147 - .suspend = m8xx_suspend, 1246 + .suspend = m8xx_sock_suspend, 1148 1247 .get_status = m8xx_get_status, 1149 1248 .set_socket = m8xx_set_socket, 1150 1249 .set_io_map = m8xx_set_io_map, 1151 1250 .set_mem_map = m8xx_set_mem_map, 1152 1251 }; 1153 1252 1154 - static int __init m8xx_init(void) 1253 + static int __init m8xx_probe(struct of_device *ofdev, const struct of_device_id *match) 1155 1254 { 1156 1255 struct pcmcia_win *w; 1157 - unsigned int i,m; 1256 + unsigned int i, m, hwirq; 1257 + pcmconf8xx_t *pcmcia; 1258 + int status; 1259 + struct device_node *np = ofdev->node; 1158 1260 1159 1261 pcmcia_info("%s\n", version); 1160 1262 1161 - if (driver_register(&m8xx_driver)) 1162 - return -1; 1263 + pcmcia = of_iomap(np, 0); 1264 + if(pcmcia == NULL) 1265 + return -EINVAL; 1266 + 1267 + pcmcia_schlvl = irq_of_parse_and_map(np, 0); 1268 + hwirq = irq_map[pcmcia_schlvl].hwirq; 1269 + if (pcmcia_schlvl < 0) 1270 + return -EINVAL; 1271 + 1272 + m8xx_pgcrx[0] = &pcmcia->pcmc_pgcra; 1273 + m8xx_pgcrx[1] = &pcmcia->pcmc_pgcrb; 1274 + 1163 1275 1164 1276 pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG 1165 - " with IRQ %u.\n", pcmcia_schlvl); 1277 + " with IRQ %u (%d). \n", pcmcia_schlvl, hwirq); 1166 1278 1167 1279 /* Configure Status change interrupt */ 1168 1280 1169 - if(request_irq(pcmcia_schlvl, m8xx_interrupt, 0, 1170 - "m8xx_pcmcia", NULL)) { 1281 + if(request_irq(pcmcia_schlvl, m8xx_interrupt, IRQF_SHARED, 1282 + driver_name, socket)) { 1171 1283 pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n", 1172 1284 pcmcia_schlvl); 1173 1285 return -1; 1174 1286 } 1175 1287 1176 - w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0; 1288 + w = (void *) &pcmcia->pcmc_pbr0; 1177 1289 1178 - out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, 1179 - M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1)); 1290 + out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1)); 1291 + clrbits32(&pcmcia->pcmc_per, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1)); 1180 1292 1181 - out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, 1182 - in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) & 1183 - ~(M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1))); 1293 + /* connect interrupt and disable CxOE */ 1184 1294 1185 - /* connect interrupt and disable CxOE */ 1295 + out_be32(M8XX_PGCRX(0), M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16)); 1296 + out_be32(M8XX_PGCRX(1), M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16)); 1186 1297 1187 - out_be32(M8XX_PGCRX(0), M8XX_PGCRX_CXOE | (mk_int_int_mask(pcmcia_schlvl) << 16)); 1188 - out_be32(M8XX_PGCRX(1), M8XX_PGCRX_CXOE | (mk_int_int_mask(pcmcia_schlvl) << 16)); 1189 - 1190 - /* intialize the fixed memory windows */ 1298 + /* intialize the fixed memory windows */ 1191 1299 1192 1300 for(i = 0; i < PCMCIA_SOCKETS_NO; i++){ 1193 - for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) { 1301 + for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) { 1194 1302 out_be32(&w->br, PCMCIA_MEM_WIN_BASE + 1195 1303 (PCMCIA_MEM_WIN_SIZE 1196 1304 * (m + i * PCMCIA_MEM_WIN_NO))); ··· 1210 1300 } 1211 1301 } 1212 1302 1213 - /* turn off voltage */ 1303 + /* turn off voltage */ 1214 1304 voltage_set(0, 0, 0); 1215 1305 voltage_set(1, 0, 0); 1216 1306 1217 - /* Enable external hardware */ 1307 + /* Enable external hardware */ 1218 1308 hardware_enable(0); 1219 1309 hardware_enable(1); 1220 - 1221 - platform_device_register(&m8xx_device); 1222 1310 1223 1311 for (i = 0 ; i < PCMCIA_SOCKETS_NO; i++) { 1224 1312 socket[i].slot = i; ··· 1225 1317 socket[i].socket.irq_mask = 0x000; 1226 1318 socket[i].socket.map_size = 0x1000; 1227 1319 socket[i].socket.io_offset = 0; 1228 - socket[i].socket.pci_irq = i ? 7 : 9; 1320 + socket[i].socket.pci_irq = pcmcia_schlvl; 1229 1321 socket[i].socket.ops = &m8xx_services; 1230 - socket[i].socket.resource_ops = &pccard_iodyn_ops; 1322 + socket[i].socket.resource_ops = &pccard_nonstatic_ops; 1231 1323 socket[i].socket.cb_dev = NULL; 1232 - socket[i].socket.dev.parent = &m8xx_device.dev; 1324 + socket[i].socket.dev.parent = &ofdev->dev; 1325 + socket[i].pcmcia = pcmcia; 1326 + socket[i].bus_freq = ppc_proc_freq; 1327 + socket[i].hwirq = hwirq; 1328 + 1329 + 1233 1330 } 1234 1331 1235 - for (i = 0; i < PCMCIA_SOCKETS_NO; i++) 1236 - pcmcia_register_socket(&socket[i].socket); 1332 + for (i = 0; i < PCMCIA_SOCKETS_NO; i++) { 1333 + status = pcmcia_register_socket(&socket[i].socket); 1334 + if (status < 0) 1335 + pcmcia_error("Socket register failed\n"); 1336 + } 1237 1337 1238 1338 return 0; 1239 1339 } 1240 1340 1241 - static void __exit m8xx_exit(void) 1341 + static int m8xx_remove(struct of_device* ofdev) 1242 1342 { 1243 - int i; 1343 + u32 m, i; 1344 + struct pcmcia_win *w; 1345 + pcmconf8xx_t *pcmcia = socket[0].pcmcia; 1244 1346 1347 + for (i = 0; i < PCMCIA_SOCKETS_NO; i++) { 1348 + w = (void *) &pcmcia->pcmc_pbr0; 1349 + 1350 + out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(i)); 1351 + out_be32(&pcmcia->pcmc_per, 1352 + in_be32(&pcmcia->pcmc_per) & ~M8XX_PCMCIA_MASK(i)); 1353 + 1354 + /* turn off interrupt and disable CxOE */ 1355 + out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE); 1356 + 1357 + /* turn off memory windows */ 1358 + for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) { 1359 + out_be32(&w->or, 0); /* set to not valid */ 1360 + w++; 1361 + } 1362 + 1363 + /* turn off voltage */ 1364 + voltage_set(i, 0, 0); 1365 + 1366 + /* disable external hardware */ 1367 + hardware_disable(i); 1368 + } 1245 1369 for (i = 0; i < PCMCIA_SOCKETS_NO; i++) 1246 1370 pcmcia_unregister_socket(&socket[i].socket); 1247 1371 1248 - m8xx_shutdown(); 1372 + free_irq(pcmcia_schlvl, NULL); 1249 1373 1250 - platform_device_unregister(&m8xx_device); 1251 - driver_unregister(&m8xx_driver); 1374 + return 0; 1375 + } 1376 + 1377 + #ifdef CONFIG_PM 1378 + static int m8xx_suspend(struct platform_device *pdev, pm_message_t state) 1379 + { 1380 + return pcmcia_socket_dev_suspend(&pdev->dev, state); 1381 + } 1382 + 1383 + static int m8xx_resume(struct platform_device *pdev) 1384 + { 1385 + return pcmcia_socket_dev_resume(&pdev->dev); 1386 + } 1387 + #else 1388 + #define m8xx_suspend NULL 1389 + #define m8xx_resume NULL 1390 + #endif 1391 + 1392 + static struct of_device_id m8xx_pcmcia_match[] = { 1393 + { 1394 + .type = "pcmcia", 1395 + .compatible = "fsl,pq-pcmcia", 1396 + }, 1397 + {}, 1398 + }; 1399 + 1400 + MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match); 1401 + 1402 + static struct of_platform_driver m8xx_pcmcia_driver = { 1403 + .name = (char *) driver_name, 1404 + .match_table = m8xx_pcmcia_match, 1405 + .probe = m8xx_probe, 1406 + .remove = m8xx_remove, 1407 + .suspend = m8xx_suspend, 1408 + .resume = m8xx_resume, 1409 + }; 1410 + 1411 + static int __init m8xx_init(void) 1412 + { 1413 + return of_register_platform_driver(&m8xx_pcmcia_driver); 1414 + } 1415 + 1416 + static void __exit m8xx_exit(void) 1417 + { 1418 + of_unregister_platform_driver(&m8xx_pcmcia_driver); 1252 1419 } 1253 1420 1254 1421 module_init(m8xx_init);
+4
include/asm-powerpc/mpc8xx.h
··· 23 23 #include <platforms/8xx/mpc885ads.h> 24 24 #endif 25 25 26 + #ifdef CONFIG_PCMCIA_M8XX 27 + extern struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops; 28 + #endif 29 + 26 30 #endif /* CONFIG_8xx */ 27 31 #endif /* __CONFIG_8xx_DEFS */ 28 32 #endif /* __KERNEL__ */
+5
include/linux/fsl_devices.h
··· 120 120 u32 sysclk; 121 121 }; 122 122 123 + struct mpc8xx_pcmcia_ops { 124 + void(*hw_ctrl)(int slot, int enable); 125 + int(*voltage_set)(int slot, int vcc, int vpp); 126 + }; 127 + 123 128 #endif /* _FSL_DEVICE_H_ */ 124 129 #endif /* __KERNEL__ */