diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-16 20:58:08 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-16 20:58:08 -0400 |
commit | 489de30259e667d7bc47da9da44a0270b050cd97 (patch) | |
tree | 6807814f443fe2c5d041c3bc3fe3ca8d22a955ca /drivers/pcmcia | |
parent | 1f1c2881f673671539b25686df463518d69c4649 (diff) | |
parent | bf22f6fe2d72b4d7e9035be8ceb340414cf490e3 (diff) |
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (209 commits)
[POWERPC] Create add_rtc() function to enable the RTC CMOS driver
[POWERPC] Add H_ILLAN_ATTRIBUTES hcall number
[POWERPC] xilinxfb: Parameterize xilinxfb platform device registration
[POWERPC] Oprofile support for Power 5++
[POWERPC] Enable arbitary speed tty ioctls and split input/output speed
[POWERPC] Make drivers/char/hvc_console.c:khvcd() static
[POWERPC] Remove dead code for preventing pread() and pwrite() calls
[POWERPC] Remove unnecessary #undef printk from prom.c
[POWERPC] Fix typo in Ebony default DTS
[POWERPC] Check for NULL ppc_md.init_IRQ() before calling
[POWERPC] Remove extra return statement
[POWERPC] pasemi: Don't auto-select CONFIG_EMBEDDED
[POWERPC] pasemi: Rename platform
[POWERPC] arch/powerpc/kernel/sysfs.c: Move NUMA exports
[POWERPC] Add __read_mostly support for powerpc
[POWERPC] Modify sched_clock() to make CONFIG_PRINTK_TIME more sane
[POWERPC] Create a dummy zImage if no valid platform has been selected
[POWERPC] PS3: Bootwrapper support.
[POWERPC] powermac i2c: Use mutex
[POWERPC] Schedule removal of arch/ppc
...
Fixed up conflicts manually in:
Documentation/feature-removal-schedule.txt
arch/powerpc/kernel/pci_32.c
arch/powerpc/kernel/pci_64.c
include/asm-powerpc/pci.h
and asked the powerpc people to double-check the result..
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r-- | drivers/pcmcia/Kconfig | 17 | ||||
-rw-r--r-- | drivers/pcmcia/m8xx_pcmcia.c | 351 |
2 files changed, 176 insertions, 192 deletions
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index 35f88649d3b7..c0c77f82d051 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig | |||
@@ -180,14 +180,15 @@ config TCIC | |||
180 | PCMCIA cards are plugged into. If unsure, say N. | 180 | PCMCIA cards are plugged into. If unsure, say N. |
181 | 181 | ||
182 | config PCMCIA_M8XX | 182 | config PCMCIA_M8XX |
183 | tristate "MPC8xx PCMCIA support" | 183 | tristate "MPC8xx PCMCIA support" |
184 | depends on PCMCIA && PPC && 8xx | 184 | depends on PCMCIA && PPC && 8xx |
185 | select PCCARD_IODYN | 185 | select PCCARD_IODYN |
186 | help | 186 | select PCCARD_NONSTATIC |
187 | Say Y here to include support for PowerPC 8xx series PCMCIA | 187 | help |
188 | controller. | 188 | Say Y here to include support for PowerPC 8xx series PCMCIA |
189 | 189 | controller. | |
190 | This driver is also available as a module called m8xx_pcmcia. | 190 | |
191 | This driver is also available as a module called m8xx_pcmcia. | ||
191 | 192 | ||
192 | config HD64465_PCMCIA | 193 | config HD64465_PCMCIA |
193 | tristate "HD64465 host bridge support" | 194 | tristate "HD64465 host bridge support" |
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c index 9721ed7bf502..3b40f9623cc9 100644 --- a/drivers/pcmcia/m8xx_pcmcia.c +++ b/drivers/pcmcia/m8xx_pcmcia.c | |||
@@ -10,7 +10,7 @@ | |||
10 | * Further fixes, v2.6 kernel port | 10 | * Further fixes, v2.6 kernel port |
11 | * <marcelo.tosatti@cyclades.com> | 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 | * <vbordug@ru.mvista.com> | 14 | * <vbordug@ru.mvista.com> |
15 | * | 15 | * |
16 | * "The ExCA standard specifies that socket controllers should provide | 16 | * "The ExCA standard specifies that socket controllers should provide |
@@ -40,10 +40,6 @@ | |||
40 | #include <linux/fcntl.h> | 40 | #include <linux/fcntl.h> |
41 | #include <linux/string.h> | 41 | #include <linux/string.h> |
42 | 42 | ||
43 | #include <asm/io.h> | ||
44 | #include <asm/bitops.h> | ||
45 | #include <asm/system.h> | ||
46 | |||
47 | #include <linux/kernel.h> | 43 | #include <linux/kernel.h> |
48 | #include <linux/errno.h> | 44 | #include <linux/errno.h> |
49 | #include <linux/slab.h> | 45 | #include <linux/slab.h> |
@@ -51,11 +47,18 @@ | |||
51 | #include <linux/ioport.h> | 47 | #include <linux/ioport.h> |
52 | #include <linux/delay.h> | 48 | #include <linux/delay.h> |
53 | #include <linux/interrupt.h> | 49 | #include <linux/interrupt.h> |
54 | #include <linux/platform_device.h> | 50 | #include <linux/fsl_devices.h> |
55 | 51 | ||
52 | #include <asm/io.h> | ||
53 | #include <asm/bitops.h> | ||
54 | #include <asm/system.h> | ||
55 | #include <asm/time.h> | ||
56 | #include <asm/mpc8xx.h> | 56 | #include <asm/mpc8xx.h> |
57 | #include <asm/8xx_immap.h> | 57 | #include <asm/8xx_immap.h> |
58 | #include <asm/irq.h> | 58 | #include <asm/irq.h> |
59 | #include <asm/fs_pd.h> | ||
60 | #include <asm/of_device.h> | ||
61 | #include <asm/of_platform.h> | ||
59 | 62 | ||
60 | #include <pcmcia/version.h> | 63 | #include <pcmcia/version.h> |
61 | #include <pcmcia/cs_types.h> | 64 | #include <pcmcia/cs_types.h> |
@@ -146,27 +149,17 @@ MODULE_LICENSE("Dual MPL/GPL"); | |||
146 | #define PCMCIA_MEM_WIN_BASE 0xe0000000 /* base address for memory window 0 */ | 149 | #define PCMCIA_MEM_WIN_BASE 0xe0000000 /* base address for memory window 0 */ |
147 | #define PCMCIA_MEM_WIN_SIZE 0x04000000 /* each memory window is 64 MByte */ | 150 | #define PCMCIA_MEM_WIN_SIZE 0x04000000 /* each memory window is 64 MByte */ |
148 | #define PCMCIA_IO_WIN_BASE _IO_BASE /* base address for io window 0 */ | 151 | #define PCMCIA_IO_WIN_BASE _IO_BASE /* base address for io window 0 */ |
149 | |||
150 | #define PCMCIA_SCHLVL PCMCIA_INTERRUPT /* Status Change Interrupt Level */ | ||
151 | |||
152 | /* ------------------------------------------------------------------------- */ | 152 | /* ------------------------------------------------------------------------- */ |
153 | 153 | ||
154 | /* 2.4.x and newer has this always in HZ */ | 154 | static int pcmcia_schlvl; |
155 | #define M8XX_BUSFREQ ((((bd_t *)&(__res))->bi_busfreq)) | ||
156 | |||
157 | static int pcmcia_schlvl = PCMCIA_SCHLVL; | ||
158 | 155 | ||
159 | static DEFINE_SPINLOCK(events_lock); | 156 | static DEFINE_SPINLOCK(events_lock); |
160 | 157 | ||
161 | |||
162 | #define PCMCIA_SOCKET_KEY_5V 1 | 158 | #define PCMCIA_SOCKET_KEY_5V 1 |
163 | #define PCMCIA_SOCKET_KEY_LV 2 | 159 | #define PCMCIA_SOCKET_KEY_LV 2 |
164 | 160 | ||
165 | /* look up table for pgcrx registers */ | 161 | /* look up table for pgcrx registers */ |
166 | static u32 *m8xx_pgcrx[2] = { | 162 | static u32 *m8xx_pgcrx[2]; |
167 | &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcra, | ||
168 | &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcrb | ||
169 | }; | ||
170 | 163 | ||
171 | /* | 164 | /* |
172 | * This structure is used to address each window in the PCMCIA controller. | 165 | * This structure is used to address each window in the PCMCIA controller. |
@@ -228,11 +221,16 @@ struct event_table { | |||
228 | u32 eventbit; | 221 | u32 eventbit; |
229 | }; | 222 | }; |
230 | 223 | ||
224 | static const char driver_name[] = "m8xx-pcmcia"; | ||
225 | |||
231 | struct socket_info { | 226 | struct socket_info { |
232 | void (*handler)(void *info, u32 events); | 227 | void (*handler)(void *info, u32 events); |
233 | void *info; | 228 | void *info; |
234 | 229 | ||
235 | u32 slot; | 230 | u32 slot; |
231 | pcmconf8xx_t *pcmcia; | ||
232 | u32 bus_freq; | ||
233 | int hwirq; | ||
236 | 234 | ||
237 | socket_state_t state; | 235 | socket_state_t state; |
238 | struct pccard_mem_map mem_win[PCMCIA_MEM_WIN_NO]; | 236 | struct pccard_mem_map mem_win[PCMCIA_MEM_WIN_NO]; |
@@ -408,78 +406,21 @@ static void hardware_disable(int slot) | |||
408 | #if defined(CONFIG_MPC885ADS) | 406 | #if defined(CONFIG_MPC885ADS) |
409 | 407 | ||
410 | #define PCMCIA_BOARD_MSG "MPC885ADS" | 408 | #define PCMCIA_BOARD_MSG "MPC885ADS" |
409 | #define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V | ||
411 | 410 | ||
412 | static int voltage_set(int slot, int vcc, int vpp) | 411 | static inline void hardware_enable(int slot) |
413 | { | 412 | { |
414 | u32 reg = 0; | 413 | m8xx_pcmcia_ops.hw_ctrl(slot, 1); |
415 | unsigned *bcsr_io; | ||
416 | |||
417 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | ||
418 | |||
419 | switch(vcc) { | ||
420 | case 0: | ||
421 | break; | ||
422 | case 33: | ||
423 | reg |= BCSR1_PCCVCC0; | ||
424 | break; | ||
425 | case 50: | ||
426 | reg |= BCSR1_PCCVCC1; | ||
427 | break; | ||
428 | default: | ||
429 | goto out_unmap; | ||
430 | } | ||
431 | |||
432 | switch(vpp) { | ||
433 | case 0: | ||
434 | break; | ||
435 | case 33: | ||
436 | case 50: | ||
437 | if(vcc == vpp) | ||
438 | reg |= BCSR1_PCCVPP1; | ||
439 | else | ||
440 | goto out_unmap; | ||
441 | break; | ||
442 | case 120: | ||
443 | if ((vcc == 33) || (vcc == 50)) | ||
444 | reg |= BCSR1_PCCVPP0; | ||
445 | else | ||
446 | goto out_unmap; | ||
447 | default: | ||
448 | goto out_unmap; | ||
449 | } | ||
450 | |||
451 | /* first, turn off all power */ | ||
452 | out_be32(bcsr_io, in_be32(bcsr_io) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK)); | ||
453 | |||
454 | /* enable new powersettings */ | ||
455 | out_be32(bcsr_io, in_be32(bcsr_io) | reg); | ||
456 | |||
457 | iounmap(bcsr_io); | ||
458 | return 0; | ||
459 | |||
460 | out_unmap: | ||
461 | iounmap(bcsr_io); | ||
462 | return 1; | ||
463 | } | 414 | } |
464 | 415 | ||
465 | #define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V | 416 | static inline void hardware_disable(int slot) |
466 | |||
467 | static void hardware_enable(int slot) | ||
468 | { | 417 | { |
469 | unsigned *bcsr_io; | 418 | m8xx_pcmcia_ops.hw_ctrl(slot, 0); |
470 | |||
471 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | ||
472 | out_be32(bcsr_io, in_be32(bcsr_io) & ~BCSR1_PCCEN); | ||
473 | iounmap(bcsr_io); | ||
474 | } | 419 | } |
475 | 420 | ||
476 | static void hardware_disable(int slot) | 421 | static inline int voltage_set(int slot, int vcc, int vpp) |
477 | { | 422 | { |
478 | unsigned *bcsr_io; | 423 | return m8xx_pcmcia_ops.voltage_set(slot, vcc, vpp); |
479 | |||
480 | bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); | ||
481 | out_be32(bcsr_io, in_be32(bcsr_io) | BCSR1_PCCEN); | ||
482 | iounmap(bcsr_io); | ||
483 | } | 424 | } |
484 | 425 | ||
485 | #endif | 426 | #endif |
@@ -604,48 +545,6 @@ static int voltage_set(int slot, int vcc, int vpp) | |||
604 | 545 | ||
605 | #endif /* CONFIG_PRxK */ | 546 | #endif /* CONFIG_PRxK */ |
606 | 547 | ||
607 | static void m8xx_shutdown(void) | ||
608 | { | ||
609 | u32 m, i; | ||
610 | struct pcmcia_win *w; | ||
611 | |||
612 | for(i = 0; i < PCMCIA_SOCKETS_NO; i++){ | ||
613 | w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0; | ||
614 | |||
615 | out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, M8XX_PCMCIA_MASK(i)); | ||
616 | out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) & ~M8XX_PCMCIA_MASK(i)); | ||
617 | |||
618 | /* turn off interrupt and disable CxOE */ | ||
619 | out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE); | ||
620 | |||
621 | /* turn off memory windows */ | ||
622 | for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) { | ||
623 | out_be32(&w->or, 0); /* set to not valid */ | ||
624 | w++; | ||
625 | } | ||
626 | |||
627 | /* turn off voltage */ | ||
628 | voltage_set(i, 0, 0); | ||
629 | |||
630 | /* disable external hardware */ | ||
631 | hardware_disable(i); | ||
632 | } | ||
633 | |||
634 | free_irq(pcmcia_schlvl, NULL); | ||
635 | } | ||
636 | |||
637 | static struct device_driver m8xx_driver = { | ||
638 | .name = "m8xx-pcmcia", | ||
639 | .bus = &platform_bus_type, | ||
640 | .suspend = pcmcia_socket_dev_suspend, | ||
641 | .resume = pcmcia_socket_dev_resume, | ||
642 | }; | ||
643 | |||
644 | static struct platform_device m8xx_device = { | ||
645 | .name = "m8xx-pcmcia", | ||
646 | .id = 0, | ||
647 | }; | ||
648 | |||
649 | static u32 pending_events[PCMCIA_SOCKETS_NO]; | 548 | static u32 pending_events[PCMCIA_SOCKETS_NO]; |
650 | static DEFINE_SPINLOCK(pending_event_lock); | 549 | static DEFINE_SPINLOCK(pending_event_lock); |
651 | 550 | ||
@@ -654,13 +553,14 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev) | |||
654 | struct socket_info *s; | 553 | struct socket_info *s; |
655 | struct event_table *e; | 554 | struct event_table *e; |
656 | unsigned int i, events, pscr, pipr, per; | 555 | unsigned int i, events, pscr, pipr, per; |
556 | pcmconf8xx_t *pcmcia = socket[0].pcmcia; | ||
657 | 557 | ||
658 | dprintk("Interrupt!\n"); | 558 | dprintk("Interrupt!\n"); |
659 | /* get interrupt sources */ | 559 | /* get interrupt sources */ |
660 | 560 | ||
661 | pscr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr); | 561 | pscr = in_be32(&pcmcia->pcmc_pscr); |
662 | pipr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr); | 562 | pipr = in_be32(&pcmcia->pcmc_pipr); |
663 | per = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per); | 563 | per = in_be32(&pcmcia->pcmc_per); |
664 | 564 | ||
665 | for(i = 0; i < PCMCIA_SOCKETS_NO; i++) { | 565 | for(i = 0; i < PCMCIA_SOCKETS_NO; i++) { |
666 | s = &socket[i]; | 566 | s = &socket[i]; |
@@ -724,7 +624,7 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev) | |||
724 | per &= ~M8XX_PCMCIA_RDY_L(0); | 624 | per &= ~M8XX_PCMCIA_RDY_L(0); |
725 | per &= ~M8XX_PCMCIA_RDY_L(1); | 625 | per &= ~M8XX_PCMCIA_RDY_L(1); |
726 | 626 | ||
727 | out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, per); | 627 | out_be32(&pcmcia->pcmc_per, per); |
728 | 628 | ||
729 | if (events) | 629 | if (events) |
730 | pcmcia_parse_events(&socket[i].socket, events); | 630 | pcmcia_parse_events(&socket[i].socket, events); |
@@ -732,7 +632,7 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev) | |||
732 | } | 632 | } |
733 | 633 | ||
734 | /* clear the interrupt sources */ | 634 | /* clear the interrupt sources */ |
735 | out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, pscr); | 635 | out_be32(&pcmcia->pcmc_pscr, pscr); |
736 | 636 | ||
737 | dprintk("Interrupt done.\n"); | 637 | dprintk("Interrupt done.\n"); |
738 | 638 | ||
@@ -753,7 +653,7 @@ static u32 m8xx_get_graycode(u32 size) | |||
753 | return k; | 653 | return k; |
754 | } | 654 | } |
755 | 655 | ||
756 | static u32 m8xx_get_speed(u32 ns, u32 is_io) | 656 | static u32 m8xx_get_speed(u32 ns, u32 is_io, u32 bus_freq) |
757 | { | 657 | { |
758 | u32 reg, clocks, psst, psl, psht; | 658 | u32 reg, clocks, psst, psl, psht; |
759 | 659 | ||
@@ -781,7 +681,7 @@ static u32 m8xx_get_speed(u32 ns, u32 is_io) | |||
781 | 681 | ||
782 | #define ADJ 180 /* 80 % longer accesstime - to be sure */ | 682 | #define ADJ 180 /* 80 % longer accesstime - to be sure */ |
783 | 683 | ||
784 | clocks = ((M8XX_BUSFREQ / 1000) * ns) / 1000; | 684 | clocks = ((bus_freq / 1000) * ns) / 1000; |
785 | clocks = (clocks * ADJ) / (100*1000); | 685 | clocks = (clocks * ADJ) / (100*1000); |
786 | if(clocks >= PCMCIA_BMT_LIMIT) { | 686 | if(clocks >= PCMCIA_BMT_LIMIT) { |
787 | printk( "Max access time limit reached\n"); | 687 | printk( "Max access time limit reached\n"); |
@@ -806,8 +706,9 @@ static int m8xx_get_status(struct pcmcia_socket *sock, unsigned int *value) | |||
806 | int lsock = container_of(sock, struct socket_info, socket)->slot; | 706 | int lsock = container_of(sock, struct socket_info, socket)->slot; |
807 | struct socket_info *s = &socket[lsock]; | 707 | struct socket_info *s = &socket[lsock]; |
808 | unsigned int pipr, reg; | 708 | unsigned int pipr, reg; |
709 | pcmconf8xx_t *pcmcia = s->pcmcia; | ||
809 | 710 | ||
810 | pipr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr); | 711 | pipr = in_be32(&pcmcia->pcmc_pipr); |
811 | 712 | ||
812 | *value = ((pipr & (M8XX_PCMCIA_CD1(lsock) | 713 | *value = ((pipr & (M8XX_PCMCIA_CD1(lsock) |
813 | | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0; | 714 | | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0; |
@@ -918,6 +819,7 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state) | |||
918 | struct event_table *e; | 819 | struct event_table *e; |
919 | unsigned int reg; | 820 | unsigned int reg; |
920 | unsigned long flags; | 821 | unsigned long flags; |
822 | pcmconf8xx_t *pcmcia = socket[0].pcmcia; | ||
921 | 823 | ||
922 | dprintk( "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " | 824 | dprintk( "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " |
923 | "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags, | 825 | "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags, |
@@ -927,6 +829,7 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state) | |||
927 | if(voltage_set(lsock, state->Vcc, state->Vpp)) | 829 | if(voltage_set(lsock, state->Vcc, state->Vpp)) |
928 | return -EINVAL; | 830 | return -EINVAL; |
929 | 831 | ||
832 | |||
930 | /* Take care of reset... */ | 833 | /* Take care of reset... */ |
931 | if(state->flags & SS_RESET) | 834 | if(state->flags & SS_RESET) |
932 | out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXRESET); /* active high */ | 835 | out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXRESET); /* active high */ |
@@ -982,7 +885,8 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state) | |||
982 | * If io_irq is non-zero we should enable irq. | 885 | * If io_irq is non-zero we should enable irq. |
983 | */ | 886 | */ |
984 | if(state->io_irq) { | 887 | if(state->io_irq) { |
985 | out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | mk_int_int_mask(state->io_irq) << 24); | 888 | out_be32(M8XX_PGCRX(lsock), |
889 | in_be32(M8XX_PGCRX(lsock)) | mk_int_int_mask(s->hwirq) << 24); | ||
986 | /* | 890 | /* |
987 | * Strange thing here: | 891 | * Strange thing here: |
988 | * The manual does not tell us which interrupt | 892 | * The manual does not tell us which interrupt |
@@ -1027,7 +931,7 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state) | |||
1027 | * Writing ones will clear the bits. | 931 | * Writing ones will clear the bits. |
1028 | */ | 932 | */ |
1029 | 933 | ||
1030 | out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, reg); | 934 | out_be32(&pcmcia->pcmc_pscr, reg); |
1031 | 935 | ||
1032 | /* | 936 | /* |
1033 | * Write the mask. | 937 | * Write the mask. |
@@ -1036,15 +940,8 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state) | |||
1036 | * Ones will enable the interrupt. | 940 | * Ones will enable the interrupt. |
1037 | */ | 941 | */ |
1038 | 942 | ||
1039 | /* | 943 | reg |= in_be32(&pcmcia->pcmc_per) & (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1)); |
1040 | reg |= ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per | 944 | out_be32(&pcmcia->pcmc_per, reg); |
1041 | & M8XX_PCMCIA_MASK(lsock); | ||
1042 | */ | ||
1043 | |||
1044 | reg |= in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) & | ||
1045 | (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1)); | ||
1046 | |||
1047 | out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, reg); | ||
1048 | 945 | ||
1049 | spin_unlock_irqrestore(&events_lock, flags); | 946 | spin_unlock_irqrestore(&events_lock, flags); |
1050 | 947 | ||
@@ -1062,6 +959,8 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) | |||
1062 | struct socket_info *s = &socket[lsock]; | 959 | struct socket_info *s = &socket[lsock]; |
1063 | struct pcmcia_win *w; | 960 | struct pcmcia_win *w; |
1064 | unsigned int reg, winnr; | 961 | unsigned int reg, winnr; |
962 | pcmconf8xx_t *pcmcia = s->pcmcia; | ||
963 | |||
1065 | 964 | ||
1066 | #define M8XX_SIZE (io->stop - io->start + 1) | 965 | #define M8XX_SIZE (io->stop - io->start + 1) |
1067 | #define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start) | 966 | #define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start) |
@@ -1086,7 +985,7 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) | |||
1086 | 985 | ||
1087 | /* setup registers */ | 986 | /* setup registers */ |
1088 | 987 | ||
1089 | w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0; | 988 | w = (void *) &pcmcia->pcmc_pbr0; |
1090 | w += winnr; | 989 | w += winnr; |
1091 | 990 | ||
1092 | out_be32(&w->or, 0); /* turn off window first */ | 991 | out_be32(&w->or, 0); /* turn off window first */ |
@@ -1095,12 +994,13 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) | |||
1095 | reg <<= 27; | 994 | reg <<= 27; |
1096 | reg |= M8XX_PCMCIA_POR_IO |(lsock << 2); | 995 | reg |= M8XX_PCMCIA_POR_IO |(lsock << 2); |
1097 | 996 | ||
1098 | reg |= m8xx_get_speed(io->speed, 1); | 997 | reg |= m8xx_get_speed(io->speed, 1, s->bus_freq); |
1099 | 998 | ||
1100 | if(io->flags & MAP_WRPROT) | 999 | if(io->flags & MAP_WRPROT) |
1101 | reg |= M8XX_PCMCIA_POR_WRPROT; | 1000 | reg |= M8XX_PCMCIA_POR_WRPROT; |
1102 | 1001 | ||
1103 | if(io->flags & (MAP_16BIT | MAP_AUTOSZ)) | 1002 | /*if(io->flags & (MAP_16BIT | MAP_AUTOSZ))*/ |
1003 | if(io->flags & MAP_16BIT) | ||
1104 | reg |= M8XX_PCMCIA_POR_16BIT; | 1004 | reg |= M8XX_PCMCIA_POR_16BIT; |
1105 | 1005 | ||
1106 | if(io->flags & MAP_ACTIVE) | 1006 | if(io->flags & MAP_ACTIVE) |
@@ -1117,7 +1017,7 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) | |||
1117 | 1017 | ||
1118 | /* setup registers */ | 1018 | /* setup registers */ |
1119 | 1019 | ||
1120 | w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0; | 1020 | w = (void *) &pcmcia->pcmc_pbr0; |
1121 | w += winnr; | 1021 | w += winnr; |
1122 | 1022 | ||
1123 | out_be32(&w->or, 0); /* turn off window */ | 1023 | out_be32(&w->or, 0); /* turn off window */ |
@@ -1144,6 +1044,7 @@ static int m8xx_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *m | |||
1144 | struct pcmcia_win *w; | 1044 | struct pcmcia_win *w; |
1145 | struct pccard_mem_map *old; | 1045 | struct pccard_mem_map *old; |
1146 | unsigned int reg, winnr; | 1046 | unsigned int reg, winnr; |
1047 | pcmconf8xx_t *pcmcia = s->pcmcia; | ||
1147 | 1048 | ||
1148 | dprintk( "SetMemMap(%d, %d, %#2.2x, %d ns, " | 1049 | dprintk( "SetMemMap(%d, %d, %#2.2x, %d ns, " |
1149 | "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags, | 1050 | "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags, |
@@ -1166,12 +1067,12 @@ static int m8xx_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *m | |||
1166 | 1067 | ||
1167 | /* Setup the window in the pcmcia controller */ | 1068 | /* Setup the window in the pcmcia controller */ |
1168 | 1069 | ||
1169 | w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0; | 1070 | w = (void *) &pcmcia->pcmc_pbr0; |
1170 | w += winnr; | 1071 | w += winnr; |
1171 | 1072 | ||
1172 | reg |= lsock << 2; | 1073 | reg |= lsock << 2; |
1173 | 1074 | ||
1174 | reg |= m8xx_get_speed(mem->speed, 0); | 1075 | reg |= m8xx_get_speed(mem->speed, 0, s->bus_freq); |
1175 | 1076 | ||
1176 | if(mem->flags & MAP_ATTRIB) | 1077 | if(mem->flags & MAP_ATTRIB) |
1177 | reg |= M8XX_PCMCIA_POR_ATTRMEM; | 1078 | reg |= M8XX_PCMCIA_POR_ATTRMEM; |
@@ -1236,60 +1137,69 @@ static int m8xx_sock_init(struct pcmcia_socket *sock) | |||
1236 | 1137 | ||
1237 | } | 1138 | } |
1238 | 1139 | ||
1239 | static int m8xx_suspend(struct pcmcia_socket *sock) | 1140 | static int m8xx_sock_suspend(struct pcmcia_socket *sock) |
1240 | { | 1141 | { |
1241 | return m8xx_set_socket(sock, &dead_socket); | 1142 | return m8xx_set_socket(sock, &dead_socket); |
1242 | } | 1143 | } |
1243 | 1144 | ||
1244 | static struct pccard_operations m8xx_services = { | 1145 | static struct pccard_operations m8xx_services = { |
1245 | .init = m8xx_sock_init, | 1146 | .init = m8xx_sock_init, |
1246 | .suspend = m8xx_suspend, | 1147 | .suspend = m8xx_sock_suspend, |
1247 | .get_status = m8xx_get_status, | 1148 | .get_status = m8xx_get_status, |
1248 | .set_socket = m8xx_set_socket, | 1149 | .set_socket = m8xx_set_socket, |
1249 | .set_io_map = m8xx_set_io_map, | 1150 | .set_io_map = m8xx_set_io_map, |
1250 | .set_mem_map = m8xx_set_mem_map, | 1151 | .set_mem_map = m8xx_set_mem_map, |
1251 | }; | 1152 | }; |
1252 | 1153 | ||
1253 | static int __init m8xx_init(void) | 1154 | static int __init m8xx_probe(struct of_device *ofdev, const struct of_device_id *match) |
1254 | { | 1155 | { |
1255 | struct pcmcia_win *w; | 1156 | struct pcmcia_win *w; |
1256 | unsigned int i,m; | 1157 | unsigned int i, m, hwirq; |
1158 | pcmconf8xx_t *pcmcia; | ||
1159 | int status; | ||
1160 | struct device_node *np = ofdev->node; | ||
1257 | 1161 | ||
1258 | pcmcia_info("%s\n", version); | 1162 | pcmcia_info("%s\n", version); |
1259 | 1163 | ||
1260 | if (driver_register(&m8xx_driver)) | 1164 | pcmcia = of_iomap(np, 0); |
1261 | return -1; | 1165 | if(pcmcia == NULL) |
1166 | return -EINVAL; | ||
1167 | |||
1168 | pcmcia_schlvl = irq_of_parse_and_map(np, 0); | ||
1169 | hwirq = irq_map[pcmcia_schlvl].hwirq; | ||
1170 | if (pcmcia_schlvl < 0) | ||
1171 | return -EINVAL; | ||
1172 | |||
1173 | m8xx_pgcrx[0] = &pcmcia->pcmc_pgcra; | ||
1174 | m8xx_pgcrx[1] = &pcmcia->pcmc_pgcrb; | ||
1175 | |||
1262 | 1176 | ||
1263 | pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG | 1177 | pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG |
1264 | " with IRQ %u.\n", pcmcia_schlvl); | 1178 | " with IRQ %u (%d). \n", pcmcia_schlvl, hwirq); |
1265 | 1179 | ||
1266 | /* Configure Status change interrupt */ | 1180 | /* Configure Status change interrupt */ |
1267 | 1181 | ||
1268 | if(request_irq(pcmcia_schlvl, m8xx_interrupt, 0, | 1182 | if(request_irq(pcmcia_schlvl, m8xx_interrupt, IRQF_SHARED, |
1269 | "m8xx_pcmcia", NULL)) { | 1183 | driver_name, socket)) { |
1270 | pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n", | 1184 | pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n", |
1271 | pcmcia_schlvl); | 1185 | pcmcia_schlvl); |
1272 | return -1; | 1186 | return -1; |
1273 | } | 1187 | } |
1274 | 1188 | ||
1275 | w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0; | 1189 | w = (void *) &pcmcia->pcmc_pbr0; |
1276 | |||
1277 | out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, | ||
1278 | M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1)); | ||
1279 | 1190 | ||
1280 | out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, | 1191 | out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1)); |
1281 | in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) & | 1192 | clrbits32(&pcmcia->pcmc_per, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1)); |
1282 | ~(M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1))); | ||
1283 | 1193 | ||
1284 | /* connect interrupt and disable CxOE */ | 1194 | /* connect interrupt and disable CxOE */ |
1285 | 1195 | ||
1286 | out_be32(M8XX_PGCRX(0), M8XX_PGCRX_CXOE | (mk_int_int_mask(pcmcia_schlvl) << 16)); | 1196 | out_be32(M8XX_PGCRX(0), M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16)); |
1287 | out_be32(M8XX_PGCRX(1), M8XX_PGCRX_CXOE | (mk_int_int_mask(pcmcia_schlvl) << 16)); | 1197 | out_be32(M8XX_PGCRX(1), M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16)); |
1288 | 1198 | ||
1289 | /* intialize the fixed memory windows */ | 1199 | /* intialize the fixed memory windows */ |
1290 | 1200 | ||
1291 | for(i = 0; i < PCMCIA_SOCKETS_NO; i++){ | 1201 | for(i = 0; i < PCMCIA_SOCKETS_NO; i++){ |
1292 | for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) { | 1202 | for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) { |
1293 | out_be32(&w->br, PCMCIA_MEM_WIN_BASE + | 1203 | out_be32(&w->br, PCMCIA_MEM_WIN_BASE + |
1294 | (PCMCIA_MEM_WIN_SIZE | 1204 | (PCMCIA_MEM_WIN_SIZE |
1295 | * (m + i * PCMCIA_MEM_WIN_NO))); | 1205 | * (m + i * PCMCIA_MEM_WIN_NO))); |
@@ -1300,16 +1210,14 @@ static int __init m8xx_init(void) | |||
1300 | } | 1210 | } |
1301 | } | 1211 | } |
1302 | 1212 | ||
1303 | /* turn off voltage */ | 1213 | /* turn off voltage */ |
1304 | voltage_set(0, 0, 0); | 1214 | voltage_set(0, 0, 0); |
1305 | voltage_set(1, 0, 0); | 1215 | voltage_set(1, 0, 0); |
1306 | 1216 | ||
1307 | /* Enable external hardware */ | 1217 | /* Enable external hardware */ |
1308 | hardware_enable(0); | 1218 | hardware_enable(0); |
1309 | hardware_enable(1); | 1219 | hardware_enable(1); |
1310 | 1220 | ||
1311 | platform_device_register(&m8xx_device); | ||
1312 | |||
1313 | for (i = 0 ; i < PCMCIA_SOCKETS_NO; i++) { | 1221 | for (i = 0 ; i < PCMCIA_SOCKETS_NO; i++) { |
1314 | socket[i].slot = i; | 1222 | socket[i].slot = i; |
1315 | socket[i].socket.owner = THIS_MODULE; | 1223 | socket[i].socket.owner = THIS_MODULE; |
@@ -1317,30 +1225,105 @@ static int __init m8xx_init(void) | |||
1317 | socket[i].socket.irq_mask = 0x000; | 1225 | socket[i].socket.irq_mask = 0x000; |
1318 | socket[i].socket.map_size = 0x1000; | 1226 | socket[i].socket.map_size = 0x1000; |
1319 | socket[i].socket.io_offset = 0; | 1227 | socket[i].socket.io_offset = 0; |
1320 | socket[i].socket.pci_irq = i ? 7 : 9; | 1228 | socket[i].socket.pci_irq = pcmcia_schlvl; |
1321 | socket[i].socket.ops = &m8xx_services; | 1229 | socket[i].socket.ops = &m8xx_services; |
1322 | socket[i].socket.resource_ops = &pccard_iodyn_ops; | 1230 | socket[i].socket.resource_ops = &pccard_nonstatic_ops; |
1323 | socket[i].socket.cb_dev = NULL; | 1231 | socket[i].socket.cb_dev = NULL; |
1324 | socket[i].socket.dev.parent = &m8xx_device.dev; | 1232 | socket[i].socket.dev.parent = &ofdev->dev; |
1233 | socket[i].pcmcia = pcmcia; | ||
1234 | socket[i].bus_freq = ppc_proc_freq; | ||
1235 | socket[i].hwirq = hwirq; | ||
1236 | |||
1237 | |||
1325 | } | 1238 | } |
1326 | 1239 | ||
1327 | for (i = 0; i < PCMCIA_SOCKETS_NO; i++) | 1240 | for (i = 0; i < PCMCIA_SOCKETS_NO; i++) { |
1328 | pcmcia_register_socket(&socket[i].socket); | 1241 | status = pcmcia_register_socket(&socket[i].socket); |
1242 | if (status < 0) | ||
1243 | pcmcia_error("Socket register failed\n"); | ||
1244 | } | ||
1329 | 1245 | ||
1330 | return 0; | 1246 | return 0; |
1331 | } | 1247 | } |
1332 | 1248 | ||
1333 | static void __exit m8xx_exit(void) | 1249 | static int m8xx_remove(struct of_device* ofdev) |
1334 | { | 1250 | { |
1335 | int i; | 1251 | u32 m, i; |
1252 | struct pcmcia_win *w; | ||
1253 | pcmconf8xx_t *pcmcia = socket[0].pcmcia; | ||
1254 | |||
1255 | for (i = 0; i < PCMCIA_SOCKETS_NO; i++) { | ||
1256 | w = (void *) &pcmcia->pcmc_pbr0; | ||
1257 | |||
1258 | out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(i)); | ||
1259 | out_be32(&pcmcia->pcmc_per, | ||
1260 | in_be32(&pcmcia->pcmc_per) & ~M8XX_PCMCIA_MASK(i)); | ||
1336 | 1261 | ||
1262 | /* turn off interrupt and disable CxOE */ | ||
1263 | out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE); | ||
1264 | |||
1265 | /* turn off memory windows */ | ||
1266 | for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) { | ||
1267 | out_be32(&w->or, 0); /* set to not valid */ | ||
1268 | w++; | ||
1269 | } | ||
1270 | |||
1271 | /* turn off voltage */ | ||
1272 | voltage_set(i, 0, 0); | ||
1273 | |||
1274 | /* disable external hardware */ | ||
1275 | hardware_disable(i); | ||
1276 | } | ||
1337 | for (i = 0; i < PCMCIA_SOCKETS_NO; i++) | 1277 | for (i = 0; i < PCMCIA_SOCKETS_NO; i++) |
1338 | pcmcia_unregister_socket(&socket[i].socket); | 1278 | pcmcia_unregister_socket(&socket[i].socket); |
1339 | 1279 | ||
1340 | m8xx_shutdown(); | 1280 | free_irq(pcmcia_schlvl, NULL); |
1341 | 1281 | ||
1342 | platform_device_unregister(&m8xx_device); | 1282 | return 0; |
1343 | driver_unregister(&m8xx_driver); | 1283 | } |
1284 | |||
1285 | #ifdef CONFIG_PM | ||
1286 | static int m8xx_suspend(struct platform_device *pdev, pm_message_t state) | ||
1287 | { | ||
1288 | return pcmcia_socket_dev_suspend(&pdev->dev, state); | ||
1289 | } | ||
1290 | |||
1291 | static int m8xx_resume(struct platform_device *pdev) | ||
1292 | { | ||
1293 | return pcmcia_socket_dev_resume(&pdev->dev); | ||
1294 | } | ||
1295 | #else | ||
1296 | #define m8xx_suspend NULL | ||
1297 | #define m8xx_resume NULL | ||
1298 | #endif | ||
1299 | |||
1300 | static struct of_device_id m8xx_pcmcia_match[] = { | ||
1301 | { | ||
1302 | .type = "pcmcia", | ||
1303 | .compatible = "fsl,pq-pcmcia", | ||
1304 | }, | ||
1305 | {}, | ||
1306 | }; | ||
1307 | |||
1308 | MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match); | ||
1309 | |||
1310 | static struct of_platform_driver m8xx_pcmcia_driver = { | ||
1311 | .name = (char *) driver_name, | ||
1312 | .match_table = m8xx_pcmcia_match, | ||
1313 | .probe = m8xx_probe, | ||
1314 | .remove = m8xx_remove, | ||
1315 | .suspend = m8xx_suspend, | ||
1316 | .resume = m8xx_resume, | ||
1317 | }; | ||
1318 | |||
1319 | static int __init m8xx_init(void) | ||
1320 | { | ||
1321 | return of_register_platform_driver(&m8xx_pcmcia_driver); | ||
1322 | } | ||
1323 | |||
1324 | static void __exit m8xx_exit(void) | ||
1325 | { | ||
1326 | of_unregister_platform_driver(&m8xx_pcmcia_driver); | ||
1344 | } | 1327 | } |
1345 | 1328 | ||
1346 | module_init(m8xx_init); | 1329 | module_init(m8xx_init); |