root / hw / pxa2xx_pcmcia.c @ c65adf9b
History | View | Annotate | Download (5.2 kB)
1 | a171fe39 | balrog | /*
|
---|---|---|---|
2 | a171fe39 | balrog | * Intel XScale PXA255/270 PC Card and CompactFlash Interface.
|
3 | a171fe39 | balrog | *
|
4 | a171fe39 | balrog | * Copyright (c) 2006 Openedhand Ltd.
|
5 | a171fe39 | balrog | * Written by Andrzej Zaborowski <balrog@zabor.org>
|
6 | a171fe39 | balrog | *
|
7 | a171fe39 | balrog | * This code is licensed under the GPLv2.
|
8 | a171fe39 | balrog | */
|
9 | a171fe39 | balrog | |
10 | 87ecb68b | pbrook | #include "hw.h" |
11 | 87ecb68b | pbrook | #include "pcmcia.h" |
12 | 9596ebb7 | pbrook | #include "pxa.h" |
13 | a171fe39 | balrog | |
14 | 4beeaa71 | Benoît Canet | |
15 | bc24a225 | Paul Brook | struct PXA2xxPCMCIAState {
|
16 | bc24a225 | Paul Brook | PCMCIASocket slot; |
17 | bc24a225 | Paul Brook | PCMCIACardState *card; |
18 | 354a8c06 | Benoît Canet | MemoryRegion common_iomem; |
19 | 4beeaa71 | Benoît Canet | MemoryRegion attr_iomem; |
20 | 59aee13c | Benoît Canet | MemoryRegion iomem; |
21 | a171fe39 | balrog | |
22 | a171fe39 | balrog | qemu_irq irq; |
23 | a171fe39 | balrog | qemu_irq cd_irq; |
24 | a171fe39 | balrog | }; |
25 | a171fe39 | balrog | |
26 | 354a8c06 | Benoît Canet | static uint64_t pxa2xx_pcmcia_common_read(void *opaque, |
27 | 354a8c06 | Benoît Canet | target_phys_addr_t offset, unsigned size)
|
28 | a171fe39 | balrog | { |
29 | bc24a225 | Paul Brook | PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; |
30 | a171fe39 | balrog | |
31 | a171fe39 | balrog | if (s->slot.attached) {
|
32 | a171fe39 | balrog | return s->card->common_read(s->card->state, offset);
|
33 | a171fe39 | balrog | } |
34 | a171fe39 | balrog | |
35 | a171fe39 | balrog | return 0; |
36 | a171fe39 | balrog | } |
37 | a171fe39 | balrog | |
38 | 354a8c06 | Benoît Canet | static void pxa2xx_pcmcia_common_write(void *opaque, target_phys_addr_t offset, |
39 | 354a8c06 | Benoît Canet | uint64_t value, unsigned size)
|
40 | a171fe39 | balrog | { |
41 | bc24a225 | Paul Brook | PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; |
42 | a171fe39 | balrog | |
43 | a171fe39 | balrog | if (s->slot.attached) {
|
44 | a171fe39 | balrog | s->card->common_write(s->card->state, offset, value); |
45 | a171fe39 | balrog | } |
46 | a171fe39 | balrog | } |
47 | a171fe39 | balrog | |
48 | 4beeaa71 | Benoît Canet | static uint64_t pxa2xx_pcmcia_attr_read(void *opaque, |
49 | 4beeaa71 | Benoît Canet | target_phys_addr_t offset, unsigned size)
|
50 | a171fe39 | balrog | { |
51 | bc24a225 | Paul Brook | PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; |
52 | a171fe39 | balrog | |
53 | a171fe39 | balrog | if (s->slot.attached) {
|
54 | a171fe39 | balrog | return s->card->attr_read(s->card->state, offset);
|
55 | a171fe39 | balrog | } |
56 | a171fe39 | balrog | |
57 | a171fe39 | balrog | return 0; |
58 | a171fe39 | balrog | } |
59 | a171fe39 | balrog | |
60 | 4beeaa71 | Benoît Canet | static void pxa2xx_pcmcia_attr_write(void *opaque, target_phys_addr_t offset, |
61 | 4beeaa71 | Benoît Canet | uint64_t value, unsigned size)
|
62 | a171fe39 | balrog | { |
63 | bc24a225 | Paul Brook | PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; |
64 | a171fe39 | balrog | |
65 | a171fe39 | balrog | if (s->slot.attached) {
|
66 | a171fe39 | balrog | s->card->attr_write(s->card->state, offset, value); |
67 | a171fe39 | balrog | } |
68 | a171fe39 | balrog | } |
69 | a171fe39 | balrog | |
70 | 59aee13c | Benoît Canet | static uint64_t pxa2xx_pcmcia_io_read(void *opaque, |
71 | 59aee13c | Benoît Canet | target_phys_addr_t offset, unsigned size)
|
72 | a171fe39 | balrog | { |
73 | bc24a225 | Paul Brook | PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; |
74 | a171fe39 | balrog | |
75 | a171fe39 | balrog | if (s->slot.attached) {
|
76 | a171fe39 | balrog | return s->card->io_read(s->card->state, offset);
|
77 | a171fe39 | balrog | } |
78 | a171fe39 | balrog | |
79 | a171fe39 | balrog | return 0; |
80 | a171fe39 | balrog | } |
81 | a171fe39 | balrog | |
82 | 59aee13c | Benoît Canet | static void pxa2xx_pcmcia_io_write(void *opaque, target_phys_addr_t offset, |
83 | 59aee13c | Benoît Canet | uint64_t value, unsigned size)
|
84 | a171fe39 | balrog | { |
85 | bc24a225 | Paul Brook | PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; |
86 | a171fe39 | balrog | |
87 | a171fe39 | balrog | if (s->slot.attached) {
|
88 | a171fe39 | balrog | s->card->io_write(s->card->state, offset, value); |
89 | a171fe39 | balrog | } |
90 | a171fe39 | balrog | } |
91 | a171fe39 | balrog | |
92 | 354a8c06 | Benoît Canet | static const MemoryRegionOps pxa2xx_pcmcia_common_ops = { |
93 | 354a8c06 | Benoît Canet | .read = pxa2xx_pcmcia_common_read, |
94 | 354a8c06 | Benoît Canet | .write = pxa2xx_pcmcia_common_write, |
95 | 354a8c06 | Benoît Canet | .endianness = DEVICE_NATIVE_ENDIAN |
96 | a171fe39 | balrog | }; |
97 | a171fe39 | balrog | |
98 | 4beeaa71 | Benoît Canet | static const MemoryRegionOps pxa2xx_pcmcia_attr_ops = { |
99 | 4beeaa71 | Benoît Canet | .read = pxa2xx_pcmcia_attr_read, |
100 | 4beeaa71 | Benoît Canet | .write = pxa2xx_pcmcia_attr_write, |
101 | 4beeaa71 | Benoît Canet | .endianness = DEVICE_NATIVE_ENDIAN |
102 | a171fe39 | balrog | }; |
103 | a171fe39 | balrog | |
104 | 59aee13c | Benoît Canet | static const MemoryRegionOps pxa2xx_pcmcia_io_ops = { |
105 | 59aee13c | Benoît Canet | .read = pxa2xx_pcmcia_io_read, |
106 | 59aee13c | Benoît Canet | .write = pxa2xx_pcmcia_io_write, |
107 | 59aee13c | Benoît Canet | .endianness = DEVICE_NATIVE_ENDIAN |
108 | a171fe39 | balrog | }; |
109 | a171fe39 | balrog | |
110 | a171fe39 | balrog | static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level) |
111 | a171fe39 | balrog | { |
112 | bc24a225 | Paul Brook | PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; |
113 | a171fe39 | balrog | if (!s->irq)
|
114 | a171fe39 | balrog | return;
|
115 | a171fe39 | balrog | |
116 | a171fe39 | balrog | qemu_set_irq(s->irq, level); |
117 | a171fe39 | balrog | } |
118 | a171fe39 | balrog | |
119 | 354a8c06 | Benoît Canet | PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem, |
120 | 354a8c06 | Benoît Canet | target_phys_addr_t base) |
121 | a171fe39 | balrog | { |
122 | bc24a225 | Paul Brook | PXA2xxPCMCIAState *s; |
123 | a171fe39 | balrog | |
124 | bc24a225 | Paul Brook | s = (PXA2xxPCMCIAState *) |
125 | 7267c094 | Anthony Liguori | g_malloc0(sizeof(PXA2xxPCMCIAState));
|
126 | a171fe39 | balrog | |
127 | a171fe39 | balrog | /* Socket I/O Memory Space */
|
128 | 59aee13c | Benoît Canet | memory_region_init_io(&s->iomem, &pxa2xx_pcmcia_io_ops, s, |
129 | 59aee13c | Benoît Canet | "pxa2xx-pcmcia-io", 0x04000000); |
130 | 59aee13c | Benoît Canet | memory_region_add_subregion(sysmem, base | 0x00000000,
|
131 | 59aee13c | Benoît Canet | &s->iomem); |
132 | a171fe39 | balrog | |
133 | a171fe39 | balrog | /* Then next 64 MB is reserved */
|
134 | a171fe39 | balrog | |
135 | a171fe39 | balrog | /* Socket Attribute Memory Space */
|
136 | 4beeaa71 | Benoît Canet | memory_region_init_io(&s->attr_iomem, &pxa2xx_pcmcia_attr_ops, s, |
137 | 4beeaa71 | Benoît Canet | "pxa2xx-pcmcia-attribute", 0x04000000); |
138 | 4beeaa71 | Benoît Canet | memory_region_add_subregion(sysmem, base | 0x08000000,
|
139 | 4beeaa71 | Benoît Canet | &s->attr_iomem); |
140 | a171fe39 | balrog | |
141 | a171fe39 | balrog | /* Socket Common Memory Space */
|
142 | 354a8c06 | Benoît Canet | memory_region_init_io(&s->common_iomem, &pxa2xx_pcmcia_common_ops, s, |
143 | 354a8c06 | Benoît Canet | "pxa2xx-pcmcia-common", 0x04000000); |
144 | 354a8c06 | Benoît Canet | memory_region_add_subregion(sysmem, base | 0x0c000000,
|
145 | 354a8c06 | Benoît Canet | &s->common_iomem); |
146 | a171fe39 | balrog | |
147 | a171fe39 | balrog | if (base == 0x30000000) |
148 | a171fe39 | balrog | s->slot.slot_string = "PXA PC Card Socket 1";
|
149 | a171fe39 | balrog | else
|
150 | a171fe39 | balrog | s->slot.slot_string = "PXA PC Card Socket 0";
|
151 | a171fe39 | balrog | s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0]; |
152 | a171fe39 | balrog | pcmcia_socket_register(&s->slot); |
153 | 3f582262 | balrog | |
154 | a171fe39 | balrog | return s;
|
155 | a171fe39 | balrog | } |
156 | a171fe39 | balrog | |
157 | a171fe39 | balrog | /* Insert a new card into a slot */
|
158 | bc24a225 | Paul Brook | int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card) |
159 | a171fe39 | balrog | { |
160 | bc24a225 | Paul Brook | PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; |
161 | a171fe39 | balrog | if (s->slot.attached)
|
162 | a171fe39 | balrog | return -EEXIST;
|
163 | a171fe39 | balrog | |
164 | a171fe39 | balrog | if (s->cd_irq) {
|
165 | a171fe39 | balrog | qemu_irq_raise(s->cd_irq); |
166 | a171fe39 | balrog | } |
167 | a171fe39 | balrog | |
168 | a171fe39 | balrog | s->card = card; |
169 | a171fe39 | balrog | |
170 | a171fe39 | balrog | s->slot.attached = 1;
|
171 | a171fe39 | balrog | s->card->slot = &s->slot; |
172 | a171fe39 | balrog | s->card->attach(s->card->state); |
173 | a171fe39 | balrog | |
174 | a171fe39 | balrog | return 0; |
175 | a171fe39 | balrog | } |
176 | a171fe39 | balrog | |
177 | a171fe39 | balrog | /* Eject card from the slot */
|
178 | a171fe39 | balrog | int pxa2xx_pcmcia_dettach(void *opaque) |
179 | a171fe39 | balrog | { |
180 | bc24a225 | Paul Brook | PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; |
181 | a171fe39 | balrog | if (!s->slot.attached)
|
182 | a171fe39 | balrog | return -ENOENT;
|
183 | a171fe39 | balrog | |
184 | a171fe39 | balrog | s->card->detach(s->card->state); |
185 | b9d38e95 | Blue Swirl | s->card->slot = NULL;
|
186 | b9d38e95 | Blue Swirl | s->card = NULL;
|
187 | a171fe39 | balrog | |
188 | a171fe39 | balrog | s->slot.attached = 0;
|
189 | a171fe39 | balrog | |
190 | a171fe39 | balrog | if (s->irq)
|
191 | a171fe39 | balrog | qemu_irq_lower(s->irq); |
192 | a171fe39 | balrog | if (s->cd_irq)
|
193 | a171fe39 | balrog | qemu_irq_lower(s->cd_irq); |
194 | a171fe39 | balrog | |
195 | a171fe39 | balrog | return 0; |
196 | a171fe39 | balrog | } |
197 | a171fe39 | balrog | |
198 | a171fe39 | balrog | /* Who to notify on card events */
|
199 | a171fe39 | balrog | void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq) |
200 | a171fe39 | balrog | { |
201 | bc24a225 | Paul Brook | PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque; |
202 | a171fe39 | balrog | s->irq = irq; |
203 | a171fe39 | balrog | s->cd_irq = cd_irq; |
204 | a171fe39 | balrog | } |