1 // SPDX-License-Identifier: GPL-2.0-only
3 * linux/drivers/pcmcia/sa1111_generic.c
5 * We implement the generic parts of a SA1111 PCMCIA driver. This
6 * basically means we handle everything except controlling the
7 * power. Power is machine specific...
9 #include <linux/module.h>
10 #include <linux/kernel.h>
11 #include <linux/ioport.h>
12 #include <linux/device.h>
13 #include <linux/interrupt.h>
14 #include <linux/init.h>
16 #include <linux/slab.h>
18 #include <pcmcia/ss.h>
20 #include <mach/hardware.h>
21 #include <asm/hardware/sa1111.h>
22 #include <asm/mach-types.h>
25 #include "sa1111_generic.h"
28 * These are offsets from the above base.
34 #define PCSR_S0_READY (1<<0)
35 #define PCSR_S1_READY (1<<1)
36 #define PCSR_S0_DETECT (1<<2)
37 #define PCSR_S1_DETECT (1<<3)
38 #define PCSR_S0_VS1 (1<<4)
39 #define PCSR_S0_VS2 (1<<5)
40 #define PCSR_S1_VS1 (1<<6)
41 #define PCSR_S1_VS2 (1<<7)
42 #define PCSR_S0_WP (1<<8)
43 #define PCSR_S1_WP (1<<9)
44 #define PCSR_S0_BVD1 (1<<10)
45 #define PCSR_S0_BVD2 (1<<11)
46 #define PCSR_S1_BVD1 (1<<12)
47 #define PCSR_S1_BVD2 (1<<13)
49 #define PCCR_S0_RST (1<<0)
50 #define PCCR_S1_RST (1<<1)
51 #define PCCR_S0_FLT (1<<2)
52 #define PCCR_S1_FLT (1<<3)
53 #define PCCR_S0_PWAITEN (1<<4)
54 #define PCCR_S1_PWAITEN (1<<5)
55 #define PCCR_S0_PSE (1<<6)
56 #define PCCR_S1_PSE (1<<7)
58 #define PCSSR_S0_SLEEP (1<<0)
59 #define PCSSR_S1_SLEEP (1<<1)
61 #define IDX_IRQ_S0_READY_NINT (0)
62 #define IDX_IRQ_S0_CD_VALID (1)
63 #define IDX_IRQ_S0_BVD1_STSCHG (2)
64 #define IDX_IRQ_S1_READY_NINT (3)
65 #define IDX_IRQ_S1_CD_VALID (4)
66 #define IDX_IRQ_S1_BVD1_STSCHG (5)
69 void sa1111_pcmcia_socket_state(struct soc_pcmcia_socket
*skt
, struct pcmcia_state
*state
)
71 struct sa1111_pcmcia_socket
*s
= to_skt(skt
);
72 u32 status
= readl_relaxed(s
->dev
->mapbase
+ PCSR
);
76 state
->detect
= status
& PCSR_S0_DETECT
? 0 : 1;
77 state
->ready
= status
& PCSR_S0_READY
? 1 : 0;
78 state
->bvd1
= status
& PCSR_S0_BVD1
? 1 : 0;
79 state
->bvd2
= status
& PCSR_S0_BVD2
? 1 : 0;
80 state
->wrprot
= status
& PCSR_S0_WP
? 1 : 0;
81 state
->vs_3v
= status
& PCSR_S0_VS1
? 0 : 1;
82 state
->vs_Xv
= status
& PCSR_S0_VS2
? 0 : 1;
86 state
->detect
= status
& PCSR_S1_DETECT
? 0 : 1;
87 state
->ready
= status
& PCSR_S1_READY
? 1 : 0;
88 state
->bvd1
= status
& PCSR_S1_BVD1
? 1 : 0;
89 state
->bvd2
= status
& PCSR_S1_BVD2
? 1 : 0;
90 state
->wrprot
= status
& PCSR_S1_WP
? 1 : 0;
91 state
->vs_3v
= status
& PCSR_S1_VS1
? 0 : 1;
92 state
->vs_Xv
= status
& PCSR_S1_VS2
? 0 : 1;
97 int sa1111_pcmcia_configure_socket(struct soc_pcmcia_socket
*skt
, const socket_state_t
*state
)
99 struct sa1111_pcmcia_socket
*s
= to_skt(skt
);
100 u32 pccr_skt_mask
, pccr_set_mask
, val
;
105 pccr_skt_mask
= PCCR_S0_RST
|PCCR_S0_FLT
|PCCR_S0_PWAITEN
|PCCR_S0_PSE
;
109 pccr_skt_mask
= PCCR_S1_RST
|PCCR_S1_FLT
|PCCR_S1_PWAITEN
|PCCR_S1_PSE
;
119 pccr_set_mask
|= PCCR_S0_PWAITEN
|PCCR_S1_PWAITEN
;
120 if (state
->Vcc
== 50)
121 pccr_set_mask
|= PCCR_S0_PSE
|PCCR_S1_PSE
;
122 if (state
->flags
& SS_RESET
)
123 pccr_set_mask
|= PCCR_S0_RST
|PCCR_S1_RST
;
124 if (state
->flags
& SS_OUTPUT_ENA
)
125 pccr_set_mask
|= PCCR_S0_FLT
|PCCR_S1_FLT
;
127 local_irq_save(flags
);
128 val
= readl_relaxed(s
->dev
->mapbase
+ PCCR
);
129 val
&= ~pccr_skt_mask
;
130 val
|= pccr_set_mask
& pccr_skt_mask
;
131 writel_relaxed(val
, s
->dev
->mapbase
+ PCCR
);
132 local_irq_restore(flags
);
137 int sa1111_pcmcia_add(struct sa1111_dev
*dev
, struct pcmcia_low_level
*ops
,
138 int (*add
)(struct soc_pcmcia_socket
*))
140 struct sa1111_pcmcia_socket
*s
;
142 int i
, ret
= 0, irqs
[NUM_IRQS
];
144 clk
= devm_clk_get(&dev
->dev
, NULL
);
148 for (i
= 0; i
< NUM_IRQS
; i
++) {
149 irqs
[i
] = sa1111_get_irq(dev
, i
);
151 return irqs
[i
] ? : -ENXIO
;
154 ops
->socket_state
= sa1111_pcmcia_socket_state
;
156 for (i
= 0; i
< ops
->nr
; i
++) {
157 s
= kzalloc(sizeof(*s
), GFP_KERNEL
);
161 s
->soc
.nr
= ops
->first
+ i
;
164 soc_pcmcia_init_one(&s
->soc
, ops
, &dev
->dev
);
167 s
->soc
.socket
.pci_irq
= irqs
[IDX_IRQ_S1_READY_NINT
];
168 s
->soc
.stat
[SOC_STAT_CD
].irq
= irqs
[IDX_IRQ_S1_CD_VALID
];
169 s
->soc
.stat
[SOC_STAT_CD
].name
= "SA1111 CF card detect";
170 s
->soc
.stat
[SOC_STAT_BVD1
].irq
= irqs
[IDX_IRQ_S1_BVD1_STSCHG
];
171 s
->soc
.stat
[SOC_STAT_BVD1
].name
= "SA1111 CF BVD1";
173 s
->soc
.socket
.pci_irq
= irqs
[IDX_IRQ_S0_READY_NINT
];
174 s
->soc
.stat
[SOC_STAT_CD
].irq
= irqs
[IDX_IRQ_S0_CD_VALID
];
175 s
->soc
.stat
[SOC_STAT_CD
].name
= "SA1111 PCMCIA card detect";
176 s
->soc
.stat
[SOC_STAT_BVD1
].irq
= irqs
[IDX_IRQ_S0_BVD1_STSCHG
];
177 s
->soc
.stat
[SOC_STAT_BVD1
].name
= "SA1111 PCMCIA BVD1";
182 s
->next
= dev_get_drvdata(&dev
->dev
);
183 dev_set_drvdata(&dev
->dev
, s
);
191 static int pcmcia_probe(struct sa1111_dev
*dev
)
196 ret
= sa1111_enable_device(dev
);
200 dev_set_drvdata(&dev
->dev
, NULL
);
202 if (!request_mem_region(dev
->res
.start
, 512, SA1111_DRIVER_NAME(dev
))) {
203 sa1111_disable_device(dev
);
210 * Initialise the suspend state.
212 writel_relaxed(PCSSR_S0_SLEEP
| PCSSR_S1_SLEEP
, base
+ PCSSR
);
213 writel_relaxed(PCCR_S0_FLT
| PCCR_S1_FLT
, base
+ PCCR
);
216 #ifdef CONFIG_SA1100_BADGE4
217 if (machine_is_badge4())
218 ret
= pcmcia_badge4_init(dev
);
220 #ifdef CONFIG_SA1100_JORNADA720
221 if (machine_is_jornada720())
222 ret
= pcmcia_jornada720_init(dev
);
224 #ifdef CONFIG_ARCH_LUBBOCK
225 if (machine_is_lubbock())
226 ret
= pcmcia_lubbock_init(dev
);
228 #ifdef CONFIG_ASSABET_NEPONSET
229 if (machine_is_assabet())
230 ret
= pcmcia_neponset_init(dev
);
234 release_mem_region(dev
->res
.start
, 512);
235 sa1111_disable_device(dev
);
241 static int pcmcia_remove(struct sa1111_dev
*dev
)
243 struct sa1111_pcmcia_socket
*next
, *s
= dev_get_drvdata(&dev
->dev
);
245 dev_set_drvdata(&dev
->dev
, NULL
);
247 for (; s
; s
= next
) {
249 soc_pcmcia_remove_one(&s
->soc
);
253 release_mem_region(dev
->res
.start
, 512);
254 sa1111_disable_device(dev
);
258 static struct sa1111_driver pcmcia_driver
= {
260 .name
= "sa1111-pcmcia",
262 .devid
= SA1111_DEVID_PCMCIA
,
263 .probe
= pcmcia_probe
,
264 .remove
= pcmcia_remove
,
267 static int __init
sa1111_drv_pcmcia_init(void)
269 return sa1111_driver_register(&pcmcia_driver
);
272 static void __exit
sa1111_drv_pcmcia_exit(void)
274 sa1111_driver_unregister(&pcmcia_driver
);
277 fs_initcall(sa1111_drv_pcmcia_init
);
278 module_exit(sa1111_drv_pcmcia_exit
);
280 MODULE_DESCRIPTION("SA1111 PCMCIA card socket driver");
281 MODULE_LICENSE("GPL");