Statistics
| Branch: | Revision:

root / hw / misc / pxa2xx_pcmcia.c @ a8aec295

History | View | Annotate | Download (5.3 kB)

1
/*
2
 * Intel XScale PXA255/270 PC Card and CompactFlash Interface.
3
 *
4
 * Copyright (c) 2006 Openedhand Ltd.
5
 * Written by Andrzej Zaborowski <balrog@zabor.org>
6
 *
7
 * This code is licensed under the GPLv2.
8
 *
9
 * Contributions after 2012-01-13 are licensed under the terms of the
10
 * GNU GPL, version 2 or (at your option) any later version.
11
 */
12

    
13
#include "hw/hw.h"
14
#include "hw/pcmcia.h"
15
#include "hw/arm/pxa.h"
16

    
17

    
18
struct PXA2xxPCMCIAState {
19
    PCMCIASocket slot;
20
    PCMCIACardState *card;
21
    MemoryRegion common_iomem;
22
    MemoryRegion attr_iomem;
23
    MemoryRegion iomem;
24

    
25
    qemu_irq irq;
26
    qemu_irq cd_irq;
27
};
28

    
29
static uint64_t pxa2xx_pcmcia_common_read(void *opaque,
30
                hwaddr offset, unsigned size)
31
{
32
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
33

    
34
    if (s->slot.attached) {
35
        return s->card->common_read(s->card->state, offset);
36
    }
37

    
38
    return 0;
39
}
40

    
41
static void pxa2xx_pcmcia_common_write(void *opaque, hwaddr offset,
42
                                       uint64_t value, unsigned size)
43
{
44
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
45

    
46
    if (s->slot.attached) {
47
        s->card->common_write(s->card->state, offset, value);
48
    }
49
}
50

    
51
static uint64_t pxa2xx_pcmcia_attr_read(void *opaque,
52
                hwaddr offset, unsigned size)
53
{
54
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
55

    
56
    if (s->slot.attached) {
57
        return s->card->attr_read(s->card->state, offset);
58
    }
59

    
60
    return 0;
61
}
62

    
63
static void pxa2xx_pcmcia_attr_write(void *opaque, hwaddr offset,
64
                                     uint64_t value, unsigned size)
65
{
66
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
67

    
68
    if (s->slot.attached) {
69
        s->card->attr_write(s->card->state, offset, value);
70
    }
71
}
72

    
73
static uint64_t pxa2xx_pcmcia_io_read(void *opaque,
74
                hwaddr offset, unsigned size)
75
{
76
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
77

    
78
    if (s->slot.attached) {
79
        return s->card->io_read(s->card->state, offset);
80
    }
81

    
82
    return 0;
83
}
84

    
85
static void pxa2xx_pcmcia_io_write(void *opaque, hwaddr offset,
86
                                   uint64_t value, unsigned size)
87
{
88
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
89

    
90
    if (s->slot.attached) {
91
        s->card->io_write(s->card->state, offset, value);
92
    }
93
}
94

    
95
static const MemoryRegionOps pxa2xx_pcmcia_common_ops = {
96
    .read = pxa2xx_pcmcia_common_read,
97
    .write = pxa2xx_pcmcia_common_write,
98
    .endianness = DEVICE_NATIVE_ENDIAN
99
};
100

    
101
static const MemoryRegionOps pxa2xx_pcmcia_attr_ops = {
102
    .read = pxa2xx_pcmcia_attr_read,
103
    .write = pxa2xx_pcmcia_attr_write,
104
    .endianness = DEVICE_NATIVE_ENDIAN
105
};
106

    
107
static const MemoryRegionOps pxa2xx_pcmcia_io_ops = {
108
    .read = pxa2xx_pcmcia_io_read,
109
    .write = pxa2xx_pcmcia_io_write,
110
    .endianness = DEVICE_NATIVE_ENDIAN
111
};
112

    
113
static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
114
{
115
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
116
    if (!s->irq)
117
        return;
118

    
119
    qemu_set_irq(s->irq, level);
120
}
121

    
122
PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
123
                                      hwaddr base)
124
{
125
    PXA2xxPCMCIAState *s;
126

    
127
    s = (PXA2xxPCMCIAState *)
128
            g_malloc0(sizeof(PXA2xxPCMCIAState));
129

    
130
    /* Socket I/O Memory Space */
131
    memory_region_init_io(&s->iomem, &pxa2xx_pcmcia_io_ops, s,
132
                          "pxa2xx-pcmcia-io", 0x04000000);
133
    memory_region_add_subregion(sysmem, base | 0x00000000,
134
                                &s->iomem);
135

    
136
    /* Then next 64 MB is reserved */
137

    
138
    /* Socket Attribute Memory Space */
139
    memory_region_init_io(&s->attr_iomem, &pxa2xx_pcmcia_attr_ops, s,
140
                          "pxa2xx-pcmcia-attribute", 0x04000000);
141
    memory_region_add_subregion(sysmem, base | 0x08000000,
142
                                &s->attr_iomem);
143

    
144
    /* Socket Common Memory Space */
145
    memory_region_init_io(&s->common_iomem, &pxa2xx_pcmcia_common_ops, s,
146
                          "pxa2xx-pcmcia-common", 0x04000000);
147
    memory_region_add_subregion(sysmem, base | 0x0c000000,
148
                                &s->common_iomem);
149

    
150
    if (base == 0x30000000)
151
        s->slot.slot_string = "PXA PC Card Socket 1";
152
    else
153
        s->slot.slot_string = "PXA PC Card Socket 0";
154
    s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
155
    pcmcia_socket_register(&s->slot);
156

    
157
    return s;
158
}
159

    
160
/* Insert a new card into a slot */
161
int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card)
162
{
163
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
164
    if (s->slot.attached)
165
        return -EEXIST;
166

    
167
    if (s->cd_irq) {
168
        qemu_irq_raise(s->cd_irq);
169
    }
170

    
171
    s->card = card;
172

    
173
    s->slot.attached = 1;
174
    s->card->slot = &s->slot;
175
    s->card->attach(s->card->state);
176

    
177
    return 0;
178
}
179

    
180
/* Eject card from the slot */
181
int pxa2xx_pcmcia_dettach(void *opaque)
182
{
183
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
184
    if (!s->slot.attached)
185
        return -ENOENT;
186

    
187
    s->card->detach(s->card->state);
188
    s->card->slot = NULL;
189
    s->card = NULL;
190

    
191
    s->slot.attached = 0;
192

    
193
    if (s->irq)
194
        qemu_irq_lower(s->irq);
195
    if (s->cd_irq)
196
        qemu_irq_lower(s->cd_irq);
197

    
198
    return 0;
199
}
200

    
201
/* Who to notify on card events */
202
void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq)
203
{
204
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
205
    s->irq = irq;
206
    s->cd_irq = cd_irq;
207
}