aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVitaly Bordug <vitb@kernel.crashing.org>2007-07-09 14:37:35 -0400
committerKumar Gala <galak@kernel.crashing.org>2007-07-10 01:33:51 -0400
commit80128ff79d282cf71b1819dbca9b8dd47d8ed3e8 (patch)
treec09b48586370aad5bb5d424dea4401778bc1bf2a
parent90faf4fa7964a08d36160f7bc3c252866ad1275a (diff)
[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>
-rw-r--r--arch/powerpc/boot/dts/mpc885ads.dts11
-rw-r--r--arch/powerpc/platforms/8xx/m8xx_setup.c5
-rw-r--r--arch/powerpc/platforms/8xx/mpc885ads_setup.c71
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c13
-rw-r--r--arch/powerpc/sysdev/mpc8xx_pic.h11
-rw-r--r--drivers/pcmcia/Kconfig17
-rw-r--r--drivers/pcmcia/m8xx_pcmcia.c351
-rw-r--r--include/asm-powerpc/mpc8xx.h4
-rw-r--r--include/linux/fsl_devices.h5
9 files changed, 294 insertions, 194 deletions
diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts
index 110bf6170603..aee01087a932 100644
--- a/arch/powerpc/boot/dts/mpc885ads.dts
+++ b/arch/powerpc/boot/dts/mpc885ads.dts
@@ -112,6 +112,17 @@
112 compatible = "CPM"; 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 cpm@ff000000 { 126 cpm@ff000000 {
116 linux,phandle = <ff000000>; 127 linux,phandle = <ff000000>;
117 #address-cells = <1>; 128 #address-cells = <1>;
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
index 0901dbada350..f1693550c70c 100644
--- a/arch/powerpc/platforms/8xx/m8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
@@ -32,6 +32,7 @@
32#include <linux/root_dev.h> 32#include <linux/root_dev.h>
33#include <linux/time.h> 33#include <linux/time.h>
34#include <linux/rtc.h> 34#include <linux/rtc.h>
35#include <linux/fsl_devices.h>
35 36
36#include <asm/mmu.h> 37#include <asm/mmu.h>
37#include <asm/reg.h> 38#include <asm/reg.h>
@@ -49,6 +50,10 @@
49 50
50#include "sysdev/mpc8xx_pic.h" 51#include "sysdev/mpc8xx_pic.h"
51 52
53#ifdef CONFIG_PCMCIA_M8XX
54struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops;
55#endif
56
52void m8xx_calibrate_decr(void); 57void m8xx_calibrate_decr(void);
53extern void m8xx_wdt_handler_install(bd_t *bp); 58extern void m8xx_wdt_handler_install(bd_t *bp);
54extern int cpm_pic_init(void); 59extern int cpm_pic_init(void);
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
index c36e475d93dc..dc27dab48df0 100644
--- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c
+++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
@@ -22,6 +22,7 @@
22 22
23#include <linux/fs_enet_pd.h> 23#include <linux/fs_enet_pd.h>
24#include <linux/fs_uart_pd.h> 24#include <linux/fs_uart_pd.h>
25#include <linux/fsl_devices.h>
25#include <linux/mii.h> 26#include <linux/mii.h>
26 27
27#include <asm/delay.h> 28#include <asm/delay.h>
@@ -51,6 +52,70 @@ static void init_smc1_uart_ioports(struct fs_uart_platform_info* fpi);
51static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi); 52static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi);
52static void init_scc3_ioports(struct fs_platform_info* ptr); 53static void init_scc3_ioports(struct fs_platform_info* ptr);
53 54
55#ifdef CONFIG_PCMCIA_M8XX
56static void pcmcia_hw_setup(int slot, int enable)
57{
58 unsigned *bcsr_io;
59
60 bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
61 if (enable)
62 clrbits32(bcsr_io, BCSR1_PCCEN);
63 else
64 setbits32(bcsr_io, BCSR1_PCCEN);
65
66 iounmap(bcsr_io);
67}
68
69static int pcmcia_set_voltage(int slot, int vcc, int vpp)
70{
71 u32 reg = 0;
72 unsigned *bcsr_io;
73
74 bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
75
76 switch(vcc) {
77 case 0:
78 break;
79 case 33:
80 reg |= BCSR1_PCCVCC0;
81 break;
82 case 50:
83 reg |= BCSR1_PCCVCC1;
84 break;
85 default:
86 return 1;
87 }
88
89 switch(vpp) {
90 case 0:
91 break;
92 case 33:
93 case 50:
94 if(vcc == vpp)
95 reg |= BCSR1_PCCVPP1;
96 else
97 return 1;
98 break;
99 case 120:
100 if ((vcc == 33) || (vcc == 50))
101 reg |= BCSR1_PCCVPP0;
102 else
103 return 1;
104 default:
105 return 1;
106 }
107
108 /* first, turn off all power */
109 clrbits32(bcsr_io, 0x00610000);
110
111 /* enable new powersettings */
112 setbits32(bcsr_io, reg);
113
114 iounmap(bcsr_io);
115 return 0;
116}
117#endif
118
54void __init mpc885ads_board_setup(void) 119void __init mpc885ads_board_setup(void)
55{ 120{
56 cpm8xx_t *cp; 121 cpm8xx_t *cp;
@@ -115,6 +180,12 @@ void __init mpc885ads_board_setup(void)
115 immr_unmap(io_port); 180 immr_unmap(io_port);
116 181
117#endif 182#endif
183
184#ifdef CONFIG_PCMCIA_M8XX
185 /*Set up board specific hook-ups*/
186 m8xx_pcmcia_ops.hw_ctrl = pcmcia_hw_setup;
187 m8xx_pcmcia_ops.voltage_set = pcmcia_set_voltage;
188#endif
118} 189}
119 190
120 191
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index cad175724359..c0ddc80d8160 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -1028,6 +1028,19 @@ err:
1028 1028
1029arch_initcall(fs_enet_of_init); 1029arch_initcall(fs_enet_of_init);
1030 1030
1031static 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
1043arch_initcall(fsl_pcmcia_of_init);
1031 1044
1032static const char *smc_regs = "regs"; 1045static const char *smc_regs = "regs";
1033static const char *smc_pram = "pram"; 1046static const char *smc_pram = "pram";
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.h b/arch/powerpc/sysdev/mpc8xx_pic.h
index afa2ee6717c1..9fe00eebdc8b 100644
--- a/arch/powerpc/sysdev/mpc8xx_pic.h
+++ b/arch/powerpc/sysdev/mpc8xx_pic.h
@@ -4,9 +4,16 @@
4#include <linux/irq.h> 4#include <linux/irq.h>
5#include <linux/interrupt.h> 5#include <linux/interrupt.h>
6 6
7extern struct hw_interrupt_type mpc8xx_pic;
8
9int mpc8xx_pic_init(void); 7int mpc8xx_pic_init(void);
10unsigned int mpc8xx_get_irq(void); 8unsigned int mpc8xx_get_irq(void);
11 9
10/*
11 * Some internal interrupt registers use an 8-bit mask for the interrupt
12 * level instead of a number.
13 */
14static inline uint mk_int_int_mask(uint mask)
15{
16 return (1 << (7 - (mask/2)));
17}
18
12#endif /* _PPC_KERNEL_PPC8xx_H */ 19#endif /* _PPC_KERNEL_PPC8xx_H */
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
182config PCMCIA_M8XX 182config 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
192config HD64465_PCMCIA 193config 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 */ 154static int pcmcia_schlvl;
155#define M8XX_BUSFREQ ((((bd_t *)&(__res))->bi_busfreq))
156
157static int pcmcia_schlvl = PCMCIA_SCHLVL;
158 155
159static DEFINE_SPINLOCK(events_lock); 156static 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 */
166static u32 *m8xx_pgcrx[2] = { 162static 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
224static const char driver_name[] = "m8xx-pcmcia";
225
231struct socket_info { 226struct 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
412static int voltage_set(int slot, int vcc, int vpp) 411static 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
460out_unmap:
461 iounmap(bcsr_io);
462 return 1;
463} 414}
464 415
465#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V 416static inline void hardware_disable(int slot)
466
467static 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
476static void hardware_disable(int slot) 421static 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
607static 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
637static 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
644static struct platform_device m8xx_device = {
645 .name = "m8xx-pcmcia",
646 .id = 0,
647};
648
649static u32 pending_events[PCMCIA_SOCKETS_NO]; 548static u32 pending_events[PCMCIA_SOCKETS_NO];
650static DEFINE_SPINLOCK(pending_event_lock); 549static 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
756static u32 m8xx_get_speed(u32 ns, u32 is_io) 656static 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
1239static int m8xx_suspend(struct pcmcia_socket *sock) 1140static 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
1244static struct pccard_operations m8xx_services = { 1145static 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
1253static int __init m8xx_init(void) 1154static 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
1333static void __exit m8xx_exit(void) 1249static 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
1286static int m8xx_suspend(struct platform_device *pdev, pm_message_t state)
1287{
1288 return pcmcia_socket_dev_suspend(&pdev->dev, state);
1289}
1290
1291static 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
1300static struct of_device_id m8xx_pcmcia_match[] = {
1301 {
1302 .type = "pcmcia",
1303 .compatible = "fsl,pq-pcmcia",
1304 },
1305 {},
1306};
1307
1308MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match);
1309
1310static 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
1319static int __init m8xx_init(void)
1320{
1321 return of_register_platform_driver(&m8xx_pcmcia_driver);
1322}
1323
1324static void __exit m8xx_exit(void)
1325{
1326 of_unregister_platform_driver(&m8xx_pcmcia_driver);
1344} 1327}
1345 1328
1346module_init(m8xx_init); 1329module_init(m8xx_init);
diff --git a/include/asm-powerpc/mpc8xx.h b/include/asm-powerpc/mpc8xx.h
index 580371120e1a..2be014b6f57c 100644
--- a/include/asm-powerpc/mpc8xx.h
+++ b/include/asm-powerpc/mpc8xx.h
@@ -23,6 +23,10 @@
23#include <platforms/8xx/mpc885ads.h> 23#include <platforms/8xx/mpc885ads.h>
24#endif 24#endif
25 25
26#ifdef CONFIG_PCMCIA_M8XX
27extern struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops;
28#endif
29
26#endif /* CONFIG_8xx */ 30#endif /* CONFIG_8xx */
27#endif /* __CONFIG_8xx_DEFS */ 31#endif /* __CONFIG_8xx_DEFS */
28#endif /* __KERNEL__ */ 32#endif /* __KERNEL__ */
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 73710d617775..12e631f0fb77 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -120,5 +120,10 @@ struct fsl_spi_platform_data {
120 u32 sysclk; 120 u32 sysclk;
121}; 121};
122 122
123struct mpc8xx_pcmcia_ops {
124 void(*hw_ctrl)(int slot, int enable);
125 int(*voltage_set)(int slot, int vcc, int vpp);
126};
127
123#endif /* _FSL_DEVICE_H_ */ 128#endif /* _FSL_DEVICE_H_ */
124#endif /* __KERNEL__ */ 129#endif /* __KERNEL__ */