2 * Intel XScale PXA255/270 PC Card and CompactFlash Interface.
4 * Copyright (c) 2006 Openedhand Ltd.
5 * Written by Andrzej Zaborowski <balrog@zabor.org>
7 * This code is licensed under the GPLv2.
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.
14 #include "hw/sysbus.h"
15 #include "hw/pcmcia.h"
16 #include "hw/arm/pxa.h"
18 #define TYPE_PXA2XX_PCMCIA "pxa2xx-pcmcia"
19 #define PXA2XX_PCMCIA(obj) \
20 OBJECT_CHECK(PXA2xxPCMCIAState, obj, TYPE_PXA2XX_PCMCIA)
22 struct PXA2xxPCMCIAState
{
23 SysBusDevice parent_obj
;
26 MemoryRegion container_mem
;
27 MemoryRegion common_iomem
;
28 MemoryRegion attr_iomem
;
34 PCMCIACardState
*card
;
37 static uint64_t pxa2xx_pcmcia_common_read(void *opaque
,
38 hwaddr offset
, unsigned size
)
40 PXA2xxPCMCIAState
*s
= (PXA2xxPCMCIAState
*) opaque
;
43 if (s
->slot
.attached
) {
44 pcc
= PCMCIA_CARD_GET_CLASS(s
->card
);
45 return pcc
->common_read(s
->card
, offset
);
51 static void pxa2xx_pcmcia_common_write(void *opaque
, hwaddr offset
,
52 uint64_t value
, unsigned size
)
54 PXA2xxPCMCIAState
*s
= (PXA2xxPCMCIAState
*) opaque
;
57 if (s
->slot
.attached
) {
58 pcc
= PCMCIA_CARD_GET_CLASS(s
->card
);
59 pcc
->common_write(s
->card
, offset
, value
);
63 static uint64_t pxa2xx_pcmcia_attr_read(void *opaque
,
64 hwaddr offset
, unsigned size
)
66 PXA2xxPCMCIAState
*s
= (PXA2xxPCMCIAState
*) opaque
;
69 if (s
->slot
.attached
) {
70 pcc
= PCMCIA_CARD_GET_CLASS(s
->card
);
71 return pcc
->attr_read(s
->card
, offset
);
77 static void pxa2xx_pcmcia_attr_write(void *opaque
, hwaddr offset
,
78 uint64_t value
, unsigned size
)
80 PXA2xxPCMCIAState
*s
= (PXA2xxPCMCIAState
*) opaque
;
83 if (s
->slot
.attached
) {
84 pcc
= PCMCIA_CARD_GET_CLASS(s
->card
);
85 pcc
->attr_write(s
->card
, offset
, value
);
89 static uint64_t pxa2xx_pcmcia_io_read(void *opaque
,
90 hwaddr offset
, unsigned size
)
92 PXA2xxPCMCIAState
*s
= (PXA2xxPCMCIAState
*) opaque
;
95 if (s
->slot
.attached
) {
96 pcc
= PCMCIA_CARD_GET_CLASS(s
->card
);
97 return pcc
->io_read(s
->card
, offset
);
103 static void pxa2xx_pcmcia_io_write(void *opaque
, hwaddr offset
,
104 uint64_t value
, unsigned size
)
106 PXA2xxPCMCIAState
*s
= (PXA2xxPCMCIAState
*) opaque
;
107 PCMCIACardClass
*pcc
;
109 if (s
->slot
.attached
) {
110 pcc
= PCMCIA_CARD_GET_CLASS(s
->card
);
111 pcc
->io_write(s
->card
, offset
, value
);
115 static const MemoryRegionOps pxa2xx_pcmcia_common_ops
= {
116 .read
= pxa2xx_pcmcia_common_read
,
117 .write
= pxa2xx_pcmcia_common_write
,
118 .endianness
= DEVICE_NATIVE_ENDIAN
121 static const MemoryRegionOps pxa2xx_pcmcia_attr_ops
= {
122 .read
= pxa2xx_pcmcia_attr_read
,
123 .write
= pxa2xx_pcmcia_attr_write
,
124 .endianness
= DEVICE_NATIVE_ENDIAN
127 static const MemoryRegionOps pxa2xx_pcmcia_io_ops
= {
128 .read
= pxa2xx_pcmcia_io_read
,
129 .write
= pxa2xx_pcmcia_io_write
,
130 .endianness
= DEVICE_NATIVE_ENDIAN
133 static void pxa2xx_pcmcia_set_irq(void *opaque
, int line
, int level
)
135 PXA2xxPCMCIAState
*s
= (PXA2xxPCMCIAState
*) opaque
;
139 qemu_set_irq(s
->irq
, level
);
142 PXA2xxPCMCIAState
*pxa2xx_pcmcia_init(MemoryRegion
*sysmem
,
146 PXA2xxPCMCIAState
*s
;
148 dev
= qdev_create(NULL
, TYPE_PXA2XX_PCMCIA
);
149 sysbus_mmio_map(SYS_BUS_DEVICE(dev
), 0, base
);
150 s
= PXA2XX_PCMCIA(dev
);
152 if (base
== 0x30000000) {
153 s
->slot
.slot_string
= "PXA PC Card Socket 1";
155 s
->slot
.slot_string
= "PXA PC Card Socket 0";
158 qdev_init_nofail(dev
);
163 static void pxa2xx_pcmcia_realize(DeviceState
*dev
, Error
**errp
)
165 PXA2xxPCMCIAState
*s
= PXA2XX_PCMCIA(dev
);
167 pcmcia_socket_register(&s
->slot
);
170 static void pxa2xx_pcmcia_initfn(Object
*obj
)
172 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
173 PXA2xxPCMCIAState
*s
= PXA2XX_PCMCIA(obj
);
175 memory_region_init(&s
->container_mem
, obj
, "container", 0x10000000);
176 sysbus_init_mmio(sbd
, &s
->container_mem
);
178 /* Socket I/O Memory Space */
179 memory_region_init_io(&s
->iomem
, NULL
, &pxa2xx_pcmcia_io_ops
, s
,
180 "pxa2xx-pcmcia-io", 0x04000000);
181 memory_region_add_subregion(&s
->container_mem
, 0x00000000,
184 /* Then next 64 MB is reserved */
186 /* Socket Attribute Memory Space */
187 memory_region_init_io(&s
->attr_iomem
, NULL
, &pxa2xx_pcmcia_attr_ops
, s
,
188 "pxa2xx-pcmcia-attribute", 0x04000000);
189 memory_region_add_subregion(&s
->container_mem
, 0x08000000,
192 /* Socket Common Memory Space */
193 memory_region_init_io(&s
->common_iomem
, NULL
, &pxa2xx_pcmcia_common_ops
, s
,
194 "pxa2xx-pcmcia-common", 0x04000000);
195 memory_region_add_subregion(&s
->container_mem
, 0x0c000000,
198 s
->slot
.irq
= qemu_allocate_irqs(pxa2xx_pcmcia_set_irq
, s
, 1)[0];
200 object_property_add_link(obj
, "card", TYPE_PCMCIA_CARD
,
201 (Object
**)&s
->card
, NULL
);
204 /* Insert a new card into a slot */
205 int pxa2xx_pcmcia_attach(void *opaque
, PCMCIACardState
*card
)
207 PXA2xxPCMCIAState
*s
= (PXA2xxPCMCIAState
*) opaque
;
208 PCMCIACardClass
*pcc
;
210 if (s
->slot
.attached
) {
215 qemu_irq_raise(s
->cd_irq
);
219 pcc
= PCMCIA_CARD_GET_CLASS(s
->card
);
221 s
->slot
.attached
= true;
222 s
->card
->slot
= &s
->slot
;
223 pcc
->attach(s
->card
);
228 /* Eject card from the slot */
229 int pxa2xx_pcmcia_detach(void *opaque
)
231 PXA2xxPCMCIAState
*s
= (PXA2xxPCMCIAState
*) opaque
;
232 PCMCIACardClass
*pcc
;
234 if (!s
->slot
.attached
) {
238 pcc
= PCMCIA_CARD_GET_CLASS(s
->card
);
239 pcc
->detach(s
->card
);
240 s
->card
->slot
= NULL
;
243 s
->slot
.attached
= false;
246 qemu_irq_lower(s
->irq
);
249 qemu_irq_lower(s
->cd_irq
);
255 /* Who to notify on card events */
256 void pxa2xx_pcmcia_set_irq_cb(void *opaque
, qemu_irq irq
, qemu_irq cd_irq
)
258 PXA2xxPCMCIAState
*s
= (PXA2xxPCMCIAState
*) opaque
;
263 static void pxa2xx_pcmcia_class_init(ObjectClass
*oc
, void *data
)
265 DeviceClass
*dc
= DEVICE_CLASS(oc
);
267 dc
->realize
= pxa2xx_pcmcia_realize
;
270 static const TypeInfo pxa2xx_pcmcia_type_info
= {
271 .name
= TYPE_PXA2XX_PCMCIA
,
272 .parent
= TYPE_SYS_BUS_DEVICE
,
273 .instance_size
= sizeof(PXA2xxPCMCIAState
),
274 .instance_init
= pxa2xx_pcmcia_initfn
,
275 .class_init
= pxa2xx_pcmcia_class_init
,
278 static void pxa2xx_pcmcia_register_types(void)
280 type_register_static(&pxa2xx_pcmcia_type_info
);
283 type_init(pxa2xx_pcmcia_register_types
)