Statistics
| Branch: | Revision:

root / hw / pxa2xx_pcmcia.c @ 9596ebb7

History | View | Annotate | Download (5.7 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

    
10
#include "hw.h"
11
#include "pcmcia.h"
12
#include "pxa.h"
13

    
14
struct pxa2xx_pcmcia_s {
15
    struct pcmcia_socket_s slot;
16
    struct pcmcia_card_s *card;
17
    target_phys_addr_t common_base;
18
    target_phys_addr_t attr_base;
19
    target_phys_addr_t io_base;
20

    
21
    qemu_irq irq;
22
    qemu_irq cd_irq;
23
};
24

    
25
static uint32_t pxa2xx_pcmcia_common_read(void *opaque,
26
                target_phys_addr_t offset)
27
{
28
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
29

    
30
    if (s->slot.attached) {
31
        offset -= s->common_base;
32
        return s->card->common_read(s->card->state, offset);
33
    }
34

    
35
    return 0;
36
}
37

    
38
static void pxa2xx_pcmcia_common_write(void *opaque,
39
                target_phys_addr_t offset, uint32_t value)
40
{
41
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
42

    
43
    if (s->slot.attached) {
44
        offset -= s->common_base;
45
        s->card->common_write(s->card->state, offset, value);
46
    }
47
}
48

    
49
static uint32_t pxa2xx_pcmcia_attr_read(void *opaque,
50
                target_phys_addr_t offset)
51
{
52
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
53

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

    
59
    return 0;
60
}
61

    
62
static void pxa2xx_pcmcia_attr_write(void *opaque,
63
                target_phys_addr_t offset, uint32_t value)
64
{
65
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
66

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

    
73
static uint32_t pxa2xx_pcmcia_io_read(void *opaque,
74
                target_phys_addr_t offset)
75
{
76
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
77

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

    
83
    return 0;
84
}
85

    
86
static void pxa2xx_pcmcia_io_write(void *opaque,
87
                target_phys_addr_t offset, uint32_t value)
88
{
89
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
90

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

    
97
static CPUReadMemoryFunc *pxa2xx_pcmcia_common_readfn[] = {
98
    pxa2xx_pcmcia_common_read,
99
    pxa2xx_pcmcia_common_read,
100
    pxa2xx_pcmcia_common_read,
101
};
102

    
103
static CPUWriteMemoryFunc *pxa2xx_pcmcia_common_writefn[] = {
104
    pxa2xx_pcmcia_common_write,
105
    pxa2xx_pcmcia_common_write,
106
    pxa2xx_pcmcia_common_write,
107
};
108

    
109
static CPUReadMemoryFunc *pxa2xx_pcmcia_attr_readfn[] = {
110
    pxa2xx_pcmcia_attr_read,
111
    pxa2xx_pcmcia_attr_read,
112
    pxa2xx_pcmcia_attr_read,
113
};
114

    
115
static CPUWriteMemoryFunc *pxa2xx_pcmcia_attr_writefn[] = {
116
    pxa2xx_pcmcia_attr_write,
117
    pxa2xx_pcmcia_attr_write,
118
    pxa2xx_pcmcia_attr_write,
119
};
120

    
121
static CPUReadMemoryFunc *pxa2xx_pcmcia_io_readfn[] = {
122
    pxa2xx_pcmcia_io_read,
123
    pxa2xx_pcmcia_io_read,
124
    pxa2xx_pcmcia_io_read,
125
};
126

    
127
static CPUWriteMemoryFunc *pxa2xx_pcmcia_io_writefn[] = {
128
    pxa2xx_pcmcia_io_write,
129
    pxa2xx_pcmcia_io_write,
130
    pxa2xx_pcmcia_io_write,
131
};
132

    
133
static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
134
{
135
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
136
    if (!s->irq)
137
        return;
138

    
139
    qemu_set_irq(s->irq, level);
140
}
141

    
142
struct pxa2xx_pcmcia_s *pxa2xx_pcmcia_init(target_phys_addr_t base)
143
{
144
    int iomemtype;
145
    struct pxa2xx_pcmcia_s *s;
146

    
147
    s = (struct pxa2xx_pcmcia_s *)
148
            qemu_mallocz(sizeof(struct pxa2xx_pcmcia_s));
149

    
150
    /* Socket I/O Memory Space */
151
    s->io_base = base | 0x00000000;
152
    iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_io_readfn,
153
                    pxa2xx_pcmcia_io_writefn, s);
154
    cpu_register_physical_memory(s->io_base, 0x04000000, iomemtype);
155

    
156
    /* Then next 64 MB is reserved */
157

    
158
    /* Socket Attribute Memory Space */
159
    s->attr_base = base | 0x08000000;
160
    iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_attr_readfn,
161
                    pxa2xx_pcmcia_attr_writefn, s);
162
    cpu_register_physical_memory(s->attr_base, 0x04000000, iomemtype);
163

    
164
    /* Socket Common Memory Space */
165
    s->common_base = base | 0x0c000000;
166
    iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_common_readfn,
167
                    pxa2xx_pcmcia_common_writefn, s);
168
    cpu_register_physical_memory(s->common_base, 0x04000000, iomemtype);
169

    
170
    if (base == 0x30000000)
171
        s->slot.slot_string = "PXA PC Card Socket 1";
172
    else
173
        s->slot.slot_string = "PXA PC Card Socket 0";
174
    s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
175
    pcmcia_socket_register(&s->slot);
176

    
177
    return s;
178
}
179

    
180
/* Insert a new card into a slot */
181
int pxa2xx_pcmcia_attach(void *opaque, struct pcmcia_card_s *card)
182
{
183
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
184
    if (s->slot.attached)
185
        return -EEXIST;
186

    
187
    if (s->cd_irq) {
188
        qemu_irq_raise(s->cd_irq);
189
    }
190

    
191
    s->card = card;
192

    
193
    s->slot.attached = 1;
194
    s->card->slot = &s->slot;
195
    s->card->attach(s->card->state);
196

    
197
    return 0;
198
}
199

    
200
/* Eject card from the slot */
201
int pxa2xx_pcmcia_dettach(void *opaque)
202
{
203
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
204
    if (!s->slot.attached)
205
        return -ENOENT;
206

    
207
    s->card->detach(s->card->state);
208
    s->card->slot = 0;
209
    s->card = 0;
210

    
211
    s->slot.attached = 0;
212

    
213
    if (s->irq)
214
        qemu_irq_lower(s->irq);
215
    if (s->cd_irq)
216
        qemu_irq_lower(s->cd_irq);
217

    
218
    return 0;
219
}
220

    
221
/* Who to notify on card events */
222
void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq)
223
{
224
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
225
    s->irq = irq;
226
    s->cd_irq = cd_irq;
227
}