]>
Commit | Line | Data |
---|---|---|
a171fe39 AZ |
1 | /* |
2 | * Intel XScale PXA255/270 PC Card and CompactFlash Interface. | |
3 | * | |
4 | * Copyright (c) 2006 Openedhand Ltd. | |
5 | * Written by Andrzej Zaborowski <[email protected]> | |
6 | * | |
7 | * This code is licensed under the GPLv2. | |
8 | */ | |
9 | ||
87ecb68b PB |
10 | #include "hw.h" |
11 | #include "pcmcia.h" | |
9596ebb7 | 12 | #include "pxa.h" |
a171fe39 | 13 | |
bc24a225 PB |
14 | struct PXA2xxPCMCIAState { |
15 | PCMCIASocket slot; | |
16 | PCMCIACardState *card; | |
a171fe39 AZ |
17 | |
18 | qemu_irq irq; | |
19 | qemu_irq cd_irq; | |
20 | }; | |
21 | ||
22 | static uint32_t pxa2xx_pcmcia_common_read(void *opaque, | |
23 | target_phys_addr_t offset) | |
24 | { | |
bc24a225 | 25 | PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; |
a171fe39 AZ |
26 | |
27 | if (s->slot.attached) { | |
a171fe39 AZ |
28 | return s->card->common_read(s->card->state, offset); |
29 | } | |
30 | ||
31 | return 0; | |
32 | } | |
33 | ||
34 | static void pxa2xx_pcmcia_common_write(void *opaque, | |
35 | target_phys_addr_t offset, uint32_t value) | |
36 | { | |
bc24a225 | 37 | PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; |
a171fe39 AZ |
38 | |
39 | if (s->slot.attached) { | |
a171fe39 AZ |
40 | s->card->common_write(s->card->state, offset, value); |
41 | } | |
42 | } | |
43 | ||
44 | static uint32_t pxa2xx_pcmcia_attr_read(void *opaque, | |
45 | target_phys_addr_t offset) | |
46 | { | |
bc24a225 | 47 | PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; |
a171fe39 AZ |
48 | |
49 | if (s->slot.attached) { | |
a171fe39 AZ |
50 | return s->card->attr_read(s->card->state, offset); |
51 | } | |
52 | ||
53 | return 0; | |
54 | } | |
55 | ||
56 | static void pxa2xx_pcmcia_attr_write(void *opaque, | |
57 | target_phys_addr_t offset, uint32_t value) | |
58 | { | |
bc24a225 | 59 | PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; |
a171fe39 AZ |
60 | |
61 | if (s->slot.attached) { | |
a171fe39 AZ |
62 | s->card->attr_write(s->card->state, offset, value); |
63 | } | |
64 | } | |
65 | ||
66 | static uint32_t pxa2xx_pcmcia_io_read(void *opaque, | |
67 | target_phys_addr_t offset) | |
68 | { | |
bc24a225 | 69 | PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; |
a171fe39 AZ |
70 | |
71 | if (s->slot.attached) { | |
a171fe39 AZ |
72 | return s->card->io_read(s->card->state, offset); |
73 | } | |
74 | ||
75 | return 0; | |
76 | } | |
77 | ||
78 | static void pxa2xx_pcmcia_io_write(void *opaque, | |
79 | target_phys_addr_t offset, uint32_t value) | |
80 | { | |
bc24a225 | 81 | PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; |
a171fe39 AZ |
82 | |
83 | if (s->slot.attached) { | |
a171fe39 AZ |
84 | s->card->io_write(s->card->state, offset, value); |
85 | } | |
86 | } | |
87 | ||
88 | static CPUReadMemoryFunc *pxa2xx_pcmcia_common_readfn[] = { | |
89 | pxa2xx_pcmcia_common_read, | |
90 | pxa2xx_pcmcia_common_read, | |
91 | pxa2xx_pcmcia_common_read, | |
92 | }; | |
93 | ||
94 | static CPUWriteMemoryFunc *pxa2xx_pcmcia_common_writefn[] = { | |
95 | pxa2xx_pcmcia_common_write, | |
96 | pxa2xx_pcmcia_common_write, | |
97 | pxa2xx_pcmcia_common_write, | |
98 | }; | |
99 | ||
100 | static CPUReadMemoryFunc *pxa2xx_pcmcia_attr_readfn[] = { | |
101 | pxa2xx_pcmcia_attr_read, | |
102 | pxa2xx_pcmcia_attr_read, | |
103 | pxa2xx_pcmcia_attr_read, | |
104 | }; | |
105 | ||
106 | static CPUWriteMemoryFunc *pxa2xx_pcmcia_attr_writefn[] = { | |
107 | pxa2xx_pcmcia_attr_write, | |
108 | pxa2xx_pcmcia_attr_write, | |
109 | pxa2xx_pcmcia_attr_write, | |
110 | }; | |
111 | ||
112 | static CPUReadMemoryFunc *pxa2xx_pcmcia_io_readfn[] = { | |
113 | pxa2xx_pcmcia_io_read, | |
114 | pxa2xx_pcmcia_io_read, | |
115 | pxa2xx_pcmcia_io_read, | |
116 | }; | |
117 | ||
118 | static CPUWriteMemoryFunc *pxa2xx_pcmcia_io_writefn[] = { | |
119 | pxa2xx_pcmcia_io_write, | |
120 | pxa2xx_pcmcia_io_write, | |
121 | pxa2xx_pcmcia_io_write, | |
122 | }; | |
123 | ||
124 | static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level) | |
125 | { | |
bc24a225 | 126 | PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; |
a171fe39 AZ |
127 | if (!s->irq) |
128 | return; | |
129 | ||
130 | qemu_set_irq(s->irq, level); | |
131 | } | |
132 | ||
bc24a225 | 133 | PXA2xxPCMCIAState *pxa2xx_pcmcia_init(target_phys_addr_t base) |
a171fe39 AZ |
134 | { |
135 | int iomemtype; | |
bc24a225 | 136 | PXA2xxPCMCIAState *s; |
a171fe39 | 137 | |
bc24a225 PB |
138 | s = (PXA2xxPCMCIAState *) |
139 | qemu_mallocz(sizeof(PXA2xxPCMCIAState)); | |
a171fe39 AZ |
140 | |
141 | /* Socket I/O Memory Space */ | |
1eed09cb | 142 | iomemtype = cpu_register_io_memory(pxa2xx_pcmcia_io_readfn, |
a171fe39 | 143 | pxa2xx_pcmcia_io_writefn, s); |
8da3ff18 | 144 | cpu_register_physical_memory(base | 0x00000000, 0x04000000, iomemtype); |
a171fe39 AZ |
145 | |
146 | /* Then next 64 MB is reserved */ | |
147 | ||
148 | /* Socket Attribute Memory Space */ | |
1eed09cb | 149 | iomemtype = cpu_register_io_memory(pxa2xx_pcmcia_attr_readfn, |
a171fe39 | 150 | pxa2xx_pcmcia_attr_writefn, s); |
8da3ff18 | 151 | cpu_register_physical_memory(base | 0x08000000, 0x04000000, iomemtype); |
a171fe39 AZ |
152 | |
153 | /* Socket Common Memory Space */ | |
1eed09cb | 154 | iomemtype = cpu_register_io_memory(pxa2xx_pcmcia_common_readfn, |
a171fe39 | 155 | pxa2xx_pcmcia_common_writefn, s); |
8da3ff18 | 156 | cpu_register_physical_memory(base | 0x0c000000, 0x04000000, iomemtype); |
a171fe39 AZ |
157 | |
158 | if (base == 0x30000000) | |
159 | s->slot.slot_string = "PXA PC Card Socket 1"; | |
160 | else | |
161 | s->slot.slot_string = "PXA PC Card Socket 0"; | |
162 | s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0]; | |
163 | pcmcia_socket_register(&s->slot); | |
3f582262 | 164 | |
a171fe39 AZ |
165 | return s; |
166 | } | |
167 | ||
168 | /* Insert a new card into a slot */ | |
bc24a225 | 169 | int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card) |
a171fe39 | 170 | { |
bc24a225 | 171 | PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; |
a171fe39 AZ |
172 | if (s->slot.attached) |
173 | return -EEXIST; | |
174 | ||
175 | if (s->cd_irq) { | |
176 | qemu_irq_raise(s->cd_irq); | |
177 | } | |
178 | ||
179 | s->card = card; | |
180 | ||
181 | s->slot.attached = 1; | |
182 | s->card->slot = &s->slot; | |
183 | s->card->attach(s->card->state); | |
184 | ||
185 | return 0; | |
186 | } | |
187 | ||
188 | /* Eject card from the slot */ | |
189 | int pxa2xx_pcmcia_dettach(void *opaque) | |
190 | { | |
bc24a225 | 191 | PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; |
a171fe39 AZ |
192 | if (!s->slot.attached) |
193 | return -ENOENT; | |
194 | ||
195 | s->card->detach(s->card->state); | |
196 | s->card->slot = 0; | |
197 | s->card = 0; | |
198 | ||
199 | s->slot.attached = 0; | |
200 | ||
201 | if (s->irq) | |
202 | qemu_irq_lower(s->irq); | |
203 | if (s->cd_irq) | |
204 | qemu_irq_lower(s->cd_irq); | |
205 | ||
206 | return 0; | |
207 | } | |
208 | ||
209 | /* Who to notify on card events */ | |
210 | void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq) | |
211 | { | |
bc24a225 | 212 | PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; |
a171fe39 AZ |
213 | s->irq = irq; |
214 | s->cd_irq = cd_irq; | |
215 | } |