2 * linux/drivers/pcmcia/sa1111_generic.c
4 * We implement the generic parts of a SA1111 PCMCIA driver. This
5 * basically means we handle everything except controlling the
6 * power. Power is machine specific...
8 #include <linux/module.h>
9 #include <linux/kernel.h>
10 #include <linux/ioport.h>
11 #include <linux/device.h>
12 #include <linux/interrupt.h>
13 #include <linux/init.h>
15 #include <linux/slab.h>
17 #include <pcmcia/ss.h>
19 #include <mach/hardware.h>
20 #include <asm/hardware/sa1111.h>
21 #include <asm/mach-types.h>
24 #include "sa1111_generic.h"
27 * These are offsets from the above base.
33 #define PCSR_S0_READY (1<<0)
34 #define PCSR_S1_READY (1<<1)
35 #define PCSR_S0_DETECT (1<<2)
36 #define PCSR_S1_DETECT (1<<3)
37 #define PCSR_S0_VS1 (1<<4)
38 #define PCSR_S0_VS2 (1<<5)
39 #define PCSR_S1_VS1 (1<<6)
40 #define PCSR_S1_VS2 (1<<7)
41 #define PCSR_S0_WP (1<<8)
42 #define PCSR_S1_WP (1<<9)
43 #define PCSR_S0_BVD1 (1<<10)
44 #define PCSR_S0_BVD2 (1<<11)
45 #define PCSR_S1_BVD1 (1<<12)
46 #define PCSR_S1_BVD2 (1<<13)
48 #define PCCR_S0_RST (1<<0)
49 #define PCCR_S1_RST (1<<1)
50 #define PCCR_S0_FLT (1<<2)
51 #define PCCR_S1_FLT (1<<3)
52 #define PCCR_S0_PWAITEN (1<<4)
53 #define PCCR_S1_PWAITEN (1<<5)
54 #define PCCR_S0_PSE (1<<6)
55 #define PCCR_S1_PSE (1<<7)
57 #define PCSSR_S0_SLEEP (1<<0)
58 #define PCSSR_S1_SLEEP (1<<1)
60 #define IDX_IRQ_S0_READY_NINT (0)
61 #define IDX_IRQ_S0_CD_VALID (1)
62 #define IDX_IRQ_S0_BVD1_STSCHG (2)
63 #define IDX_IRQ_S1_READY_NINT (3)
64 #define IDX_IRQ_S1_CD_VALID (4)
65 #define IDX_IRQ_S1_BVD1_STSCHG (5)
67 void sa1111_pcmcia_socket_state(struct soc_pcmcia_socket
*skt
, struct pcmcia_state
*state
)
69 struct sa1111_pcmcia_socket
*s
= to_skt(skt
);
70 unsigned long status
= sa1111_readl(s
->dev
->mapbase
+ PCSR
);
74 state
->detect
= status
& PCSR_S0_DETECT
? 0 : 1;
75 state
->ready
= status
& PCSR_S0_READY
? 1 : 0;
76 state
->bvd1
= status
& PCSR_S0_BVD1
? 1 : 0;
77 state
->bvd2
= status
& PCSR_S0_BVD2
? 1 : 0;
78 state
->wrprot
= status
& PCSR_S0_WP
? 1 : 0;
79 state
->vs_3v
= status
& PCSR_S0_VS1
? 0 : 1;
80 state
->vs_Xv
= status
& PCSR_S0_VS2
? 0 : 1;
84 state
->detect
= status
& PCSR_S1_DETECT
? 0 : 1;
85 state
->ready
= status
& PCSR_S1_READY
? 1 : 0;
86 state
->bvd1
= status
& PCSR_S1_BVD1
? 1 : 0;
87 state
->bvd2
= status
& PCSR_S1_BVD2
? 1 : 0;
88 state
->wrprot
= status
& PCSR_S1_WP
? 1 : 0;
89 state
->vs_3v
= status
& PCSR_S1_VS1
? 0 : 1;
90 state
->vs_Xv
= status
& PCSR_S1_VS2
? 0 : 1;
95 int sa1111_pcmcia_configure_socket(struct soc_pcmcia_socket
*skt
, const socket_state_t
*state
)
97 struct sa1111_pcmcia_socket
*s
= to_skt(skt
);
98 unsigned int pccr_skt_mask
, pccr_set_mask
, val
;
103 pccr_skt_mask
= PCCR_S0_RST
|PCCR_S0_FLT
|PCCR_S0_PWAITEN
|PCCR_S0_PSE
;
107 pccr_skt_mask
= PCCR_S1_RST
|PCCR_S1_FLT
|PCCR_S1_PWAITEN
|PCCR_S1_PSE
;
117 pccr_set_mask
|= PCCR_S0_PWAITEN
|PCCR_S1_PWAITEN
;
118 if (state
->Vcc
== 50)
119 pccr_set_mask
|= PCCR_S0_PSE
|PCCR_S1_PSE
;
120 if (state
->flags
& SS_RESET
)
121 pccr_set_mask
|= PCCR_S0_RST
|PCCR_S1_RST
;
122 if (state
->flags
& SS_OUTPUT_ENA
)
123 pccr_set_mask
|= PCCR_S0_FLT
|PCCR_S1_FLT
;
125 local_irq_save(flags
);
126 val
= sa1111_readl(s
->dev
->mapbase
+ PCCR
);
127 val
&= ~pccr_skt_mask
;
128 val
|= pccr_set_mask
& pccr_skt_mask
;
129 sa1111_writel(val
, s
->dev
->mapbase
+ PCCR
);
130 local_irq_restore(flags
);
135 int sa1111_pcmcia_add(struct sa1111_dev
*dev
, struct pcmcia_low_level
*ops
,
136 int (*add
)(struct soc_pcmcia_socket
*))
138 struct sa1111_pcmcia_socket
*s
;
142 clk
= devm_clk_get(&dev
->dev
, NULL
);
146 ops
->socket_state
= sa1111_pcmcia_socket_state
;
148 for (i
= 0; i
< ops
->nr
; i
++) {
149 s
= kzalloc(sizeof(*s
), GFP_KERNEL
);
153 s
->soc
.nr
= ops
->first
+ i
;
156 soc_pcmcia_init_one(&s
->soc
, ops
, &dev
->dev
);
159 s
->soc
.socket
.pci_irq
= dev
->irq
[IDX_IRQ_S1_READY_NINT
];
160 s
->soc
.stat
[SOC_STAT_CD
].irq
= dev
->irq
[IDX_IRQ_S1_CD_VALID
];
161 s
->soc
.stat
[SOC_STAT_CD
].name
= "SA1111 CF card detect";
162 s
->soc
.stat
[SOC_STAT_BVD1
].irq
= dev
->irq
[IDX_IRQ_S1_BVD1_STSCHG
];
163 s
->soc
.stat
[SOC_STAT_BVD1
].name
= "SA1111 CF BVD1";
165 s
->soc
.socket
.pci_irq
= dev
->irq
[IDX_IRQ_S0_READY_NINT
];
166 s
->soc
.stat
[SOC_STAT_CD
].irq
= dev
->irq
[IDX_IRQ_S0_CD_VALID
];
167 s
->soc
.stat
[SOC_STAT_CD
].name
= "SA1111 PCMCIA card detect";
168 s
->soc
.stat
[SOC_STAT_BVD1
].irq
= dev
->irq
[IDX_IRQ_S0_BVD1_STSCHG
];
169 s
->soc
.stat
[SOC_STAT_BVD1
].name
= "SA1111 PCMCIA BVD1";
174 s
->next
= dev_get_drvdata(&dev
->dev
);
175 dev_set_drvdata(&dev
->dev
, s
);
183 static int pcmcia_probe(struct sa1111_dev
*dev
)
188 ret
= sa1111_enable_device(dev
);
192 dev_set_drvdata(&dev
->dev
, NULL
);
194 if (!request_mem_region(dev
->res
.start
, 512, SA1111_DRIVER_NAME(dev
))) {
195 sa1111_disable_device(dev
);
202 * Initialise the suspend state.
204 sa1111_writel(PCSSR_S0_SLEEP
| PCSSR_S1_SLEEP
, base
+ PCSSR
);
205 sa1111_writel(PCCR_S0_FLT
| PCCR_S1_FLT
, base
+ PCCR
);
208 #ifdef CONFIG_SA1100_BADGE4
209 if (machine_is_badge4())
210 ret
= pcmcia_badge4_init(dev
);
212 #ifdef CONFIG_SA1100_JORNADA720
213 if (machine_is_jornada720())
214 ret
= pcmcia_jornada720_init(dev
);
216 #ifdef CONFIG_ARCH_LUBBOCK
217 if (machine_is_lubbock())
218 ret
= pcmcia_lubbock_init(dev
);
220 #ifdef CONFIG_ASSABET_NEPONSET
221 if (machine_is_assabet())
222 ret
= pcmcia_neponset_init(dev
);
226 release_mem_region(dev
->res
.start
, 512);
227 sa1111_disable_device(dev
);
233 static int pcmcia_remove(struct sa1111_dev
*dev
)
235 struct sa1111_pcmcia_socket
*next
, *s
= dev_get_drvdata(&dev
->dev
);
237 dev_set_drvdata(&dev
->dev
, NULL
);
239 for (; s
; s
= next
) {
241 soc_pcmcia_remove_one(&s
->soc
);
245 release_mem_region(dev
->res
.start
, 512);
246 sa1111_disable_device(dev
);
250 static struct sa1111_driver pcmcia_driver
= {
252 .name
= "sa1111-pcmcia",
254 .devid
= SA1111_DEVID_PCMCIA
,
255 .probe
= pcmcia_probe
,
256 .remove
= pcmcia_remove
,
259 static int __init
sa1111_drv_pcmcia_init(void)
261 return sa1111_driver_register(&pcmcia_driver
);
264 static void __exit
sa1111_drv_pcmcia_exit(void)
266 sa1111_driver_unregister(&pcmcia_driver
);
269 fs_initcall(sa1111_drv_pcmcia_init
);
270 module_exit(sa1111_drv_pcmcia_exit
);
272 MODULE_DESCRIPTION("SA1111 PCMCIA card socket driver");
273 MODULE_LICENSE("GPL");