Statistics
| Branch: | Revision:

root / hw / pxa2xx_pcmcia.c @ 87ecb68b

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

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

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

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

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

    
34
    return 0;
35
}
36

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

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

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

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

    
58
    return 0;
59
}
60

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

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

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

    
77
    if (s->slot.attached) {
78
        offset -= s->io_base;
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,
86
                target_phys_addr_t offset, uint32_t value)
87
{
88
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
89

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
176
    return s;
177
}
178

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

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

    
190
    s->card = card;
191

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

    
196
    return 0;
197
}
198

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

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

    
210
    s->slot.attached = 0;
211

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

    
217
    return 0;
218
}
219

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