Statistics
| Branch: | Revision:

root / hw / misc / pxa2xx_pcmcia.c @ a8aec295

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