2 * Intel XScale PXA255/270 PC Card and CompactFlash Interface.
4 * Copyright (c) 2006 Openedhand Ltd.
5 * Written by Andrzej Zaborowski <balrog@zabor.org>
7 * This code is licensed under the GPLv2.
12 struct pxa2xx_pcmcia_s {
13 struct pcmcia_socket_s slot;
14 struct pcmcia_card_s *card;
15 target_phys_addr_t common_base;
16 target_phys_addr_t attr_base;
17 target_phys_addr_t io_base;
23 static uint32_t pxa2xx_pcmcia_common_read(void *opaque,
24 target_phys_addr_t offset)
26 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
28 if (s->slot.attached) {
29 offset -= s->common_base;
30 return s->card->common_read(s->card->state, offset);
36 static void pxa2xx_pcmcia_common_write(void *opaque,
37 target_phys_addr_t offset, uint32_t value)
39 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
41 if (s->slot.attached) {
42 offset -= s->common_base;
43 s->card->common_write(s->card->state, offset, value);
47 static uint32_t pxa2xx_pcmcia_attr_read(void *opaque,
48 target_phys_addr_t offset)
50 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
52 if (s->slot.attached) {
53 offset -= s->attr_base;
54 return s->card->attr_read(s->card->state, offset);
60 static void pxa2xx_pcmcia_attr_write(void *opaque,
61 target_phys_addr_t offset, uint32_t value)
63 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
65 if (s->slot.attached) {
66 offset -= s->attr_base;
67 s->card->attr_write(s->card->state, offset, value);
71 static uint32_t pxa2xx_pcmcia_io_read(void *opaque,
72 target_phys_addr_t offset)
74 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
76 if (s->slot.attached) {
78 return s->card->io_read(s->card->state, offset);
84 static void pxa2xx_pcmcia_io_write(void *opaque,
85 target_phys_addr_t offset, uint32_t value)
87 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
89 if (s->slot.attached) {
91 s->card->io_write(s->card->state, offset, value);
95 static CPUReadMemoryFunc *pxa2xx_pcmcia_common_readfn[] = {
96 pxa2xx_pcmcia_common_read,
97 pxa2xx_pcmcia_common_read,
98 pxa2xx_pcmcia_common_read,
101 static CPUWriteMemoryFunc *pxa2xx_pcmcia_common_writefn[] = {
102 pxa2xx_pcmcia_common_write,
103 pxa2xx_pcmcia_common_write,
104 pxa2xx_pcmcia_common_write,
107 static CPUReadMemoryFunc *pxa2xx_pcmcia_attr_readfn[] = {
108 pxa2xx_pcmcia_attr_read,
109 pxa2xx_pcmcia_attr_read,
110 pxa2xx_pcmcia_attr_read,
113 static CPUWriteMemoryFunc *pxa2xx_pcmcia_attr_writefn[] = {
114 pxa2xx_pcmcia_attr_write,
115 pxa2xx_pcmcia_attr_write,
116 pxa2xx_pcmcia_attr_write,
119 static CPUReadMemoryFunc *pxa2xx_pcmcia_io_readfn[] = {
120 pxa2xx_pcmcia_io_read,
121 pxa2xx_pcmcia_io_read,
122 pxa2xx_pcmcia_io_read,
125 static CPUWriteMemoryFunc *pxa2xx_pcmcia_io_writefn[] = {
126 pxa2xx_pcmcia_io_write,
127 pxa2xx_pcmcia_io_write,
128 pxa2xx_pcmcia_io_write,
131 static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
133 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
137 qemu_set_irq(s->irq, level);
140 struct pxa2xx_pcmcia_s *pxa2xx_pcmcia_init(target_phys_addr_t base)
143 struct pxa2xx_pcmcia_s *s;
145 s = (struct pxa2xx_pcmcia_s *)
146 qemu_mallocz(sizeof(struct pxa2xx_pcmcia_s));
148 /* Socket I/O Memory Space */
149 s->io_base = base | 0x00000000;
150 iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_io_readfn,
151 pxa2xx_pcmcia_io_writefn, s);
152 cpu_register_physical_memory(s->io_base, 0x04000000, iomemtype);
154 /* Then next 64 MB is reserved */
156 /* Socket Attribute Memory Space */
157 s->attr_base = base | 0x08000000;
158 iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_attr_readfn,
159 pxa2xx_pcmcia_attr_writefn, s);
160 cpu_register_physical_memory(s->attr_base, 0x04000000, iomemtype);
162 /* Socket Common Memory Space */
163 s->common_base = base | 0x0c000000;
164 iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_common_readfn,
165 pxa2xx_pcmcia_common_writefn, s);
166 cpu_register_physical_memory(s->common_base, 0x04000000, iomemtype);
168 if (base == 0x30000000)
169 s->slot.slot_string = "PXA PC Card Socket 1";
171 s->slot.slot_string = "PXA PC Card Socket 0";
172 s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
173 pcmcia_socket_register(&s->slot);
178 /* Insert a new card into a slot */
179 int pxa2xx_pcmcia_attach(void *opaque, struct pcmcia_card_s *card)
181 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
182 if (s->slot.attached)
186 qemu_irq_raise(s->cd_irq);
191 s->slot.attached = 1;
192 s->card->slot = &s->slot;
193 s->card->attach(s->card->state);
198 /* Eject card from the slot */
199 int pxa2xx_pcmcia_dettach(void *opaque)
201 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
202 if (!s->slot.attached)
205 s->card->detach(s->card->state);
209 s->slot.attached = 0;
212 qemu_irq_lower(s->irq);
214 qemu_irq_lower(s->cd_irq);
219 /* Who to notify on card events */
220 void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq)
222 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;