Statistics
| Branch: | Revision:

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
}