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.
13 #include "qemu/osdep.h"
15 #include "hw/sysbus.h"
16 #include "qemu/module.h"
17 #include "hw/pcmcia.h"
18 #include "hw/arm/pxa.h"
20 #define TYPE_PXA2XX_PCMCIA "pxa2xx-pcmcia"
21 #define PXA2XX_PCMCIA(obj) \
22 OBJECT_CHECK(PXA2xxPCMCIAState, obj, TYPE_PXA2XX_PCMCIA)
24 struct PXA2xxPCMCIAState
{
25 SysBusDevice parent_obj
;
28 MemoryRegion container_mem
;
29 MemoryRegion common_iomem
;
30 MemoryRegion attr_iomem
;
36 PCMCIACardState
*card
;
39 static uint64_t pxa2xx_pcmcia_common_read(void *opaque
,
40 hwaddr offset
, unsigned size
)
42 PXA2xxPCMCIAState
*s
= (PXA2xxPCMCIAState
*) opaque
;
45 if (s
->slot
.attached
) {
46 pcc
= PCMCIA_CARD_GET_CLASS(s
->card
);
47 return pcc
->common_read(s
->card
, offset
);
53 static void pxa2xx_pcmcia_common_write(void *opaque
, hwaddr offset
,
54 uint64_t value
, unsigned size
)
56 PXA2xxPCMCIAState
*s
= (PXA2xxPCMCIAState
*) opaque
;
59 if (s
->slot
.attached
) {
60 pcc
= PCMCIA_CARD_GET_CLASS(s
->card
);
61 pcc
->common_write(s
->card
, offset
, value
);
65 static uint64_t pxa2xx_pcmcia_attr_read(void *opaque
,
66 hwaddr offset
, unsigned size
)
68 PXA2xxPCMCIAState
*s
= (PXA2xxPCMCIAState
*) opaque
;
71 if (s
->slot
.attached
) {
72 pcc
= PCMCIA_CARD_GET_CLASS(s
->card
);
73 return pcc
->attr_read(s
->card
, offset
);
79 static void pxa2xx_pcmcia_attr_write(void *opaque
, hwaddr offset
,
80 uint64_t value
, unsigned size
)
82 PXA2xxPCMCIAState
*s
= (PXA2xxPCMCIAState
*) opaque
;
85 if (s
->slot
.attached
) {
86 pcc
= PCMCIA_CARD_GET_CLASS(s
->card
);
87 pcc
->attr_write(s
->card
, offset
, value
);
91 static uint64_t pxa2xx_pcmcia_io_read(void *opaque
,
92 hwaddr offset
, unsigned size
)
94 PXA2xxPCMCIAState
*s
= (PXA2xxPCMCIAState
*) opaque
;
97 if (s
->slot
.attached
) {
98 pcc
= PCMCIA_CARD_GET_CLASS(s
->card
);
99 return pcc
->io_read(s
->card
, offset
);
105 static void pxa2xx_pcmcia_io_write(void *opaque
, hwaddr offset
,
106 uint64_t value
, unsigned size
)
108 PXA2xxPCMCIAState
*s
= (PXA2xxPCMCIAState
*) opaque
;
109 PCMCIACardClass
*pcc
;
111 if (s
->slot
.attached
) {
112 pcc
= PCMCIA_CARD_GET_CLASS(s
->card
);
113 pcc
->io_write(s
->card
, offset
, value
);
117 static const MemoryRegionOps pxa2xx_pcmcia_common_ops
= {
118 .read
= pxa2xx_pcmcia_common_read
,
119 .write
= pxa2xx_pcmcia_common_write
,
120 .endianness
= DEVICE_NATIVE_ENDIAN
123 static const MemoryRegionOps pxa2xx_pcmcia_attr_ops
= {
124 .read
= pxa2xx_pcmcia_attr_read
,
125 .write
= pxa2xx_pcmcia_attr_write
,
126 .endianness
= DEVICE_NATIVE_ENDIAN
129 static const MemoryRegionOps pxa2xx_pcmcia_io_ops
= {
130 .read
= pxa2xx_pcmcia_io_read
,
131 .write
= pxa2xx_pcmcia_io_write
,
132 .endianness
= DEVICE_NATIVE_ENDIAN
135 static void pxa2xx_pcmcia_set_irq(void *opaque
, int line
, int level
)
137 PXA2xxPCMCIAState
*s
= (PXA2xxPCMCIAState
*) opaque
;
141 qemu_set_irq(s
->irq
, level
);
144 PXA2xxPCMCIAState
*pxa2xx_pcmcia_init(MemoryRegion
*sysmem
,
148 PXA2xxPCMCIAState
*s
;
150 dev
= qdev_create(NULL
, TYPE_PXA2XX_PCMCIA
);
151 sysbus_mmio_map(SYS_BUS_DEVICE(dev
), 0, base
);
152 s
= PXA2XX_PCMCIA(dev
);
154 qdev_init_nofail(dev
);
159 static void pxa2xx_pcmcia_initfn(Object
*obj
)
161 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
162 PXA2xxPCMCIAState
*s
= PXA2XX_PCMCIA(obj
);
164 memory_region_init(&s
->container_mem
, obj
, "container", 0x10000000);
165 sysbus_init_mmio(sbd
, &s
->container_mem
);
167 /* Socket I/O Memory Space */
168 memory_region_init_io(&s
->iomem
, obj
, &pxa2xx_pcmcia_io_ops
, s
,
169 "pxa2xx-pcmcia-io", 0x04000000);
170 memory_region_add_subregion(&s
->container_mem
, 0x00000000,
173 /* Then next 64 MB is reserved */
175 /* Socket Attribute Memory Space */
176 memory_region_init_io(&s
->attr_iomem
, obj
, &pxa2xx_pcmcia_attr_ops
, s
,
177 "pxa2xx-pcmcia-attribute", 0x04000000);
178 memory_region_add_subregion(&s
->container_mem
, 0x08000000,
181 /* Socket Common Memory Space */
182 memory_region_init_io(&s
->common_iomem
, obj
, &pxa2xx_pcmcia_common_ops
, s
,
183 "pxa2xx-pcmcia-common", 0x04000000);
184 memory_region_add_subregion(&s
->container_mem
, 0x0c000000,
187 s
->slot
.irq
= qemu_allocate_irq(pxa2xx_pcmcia_set_irq
, s
, 0);
189 object_property_add_link(obj
, "card", TYPE_PCMCIA_CARD
,
191 NULL
, /* read-only property */
195 /* Insert a new card into a slot */
196 int pxa2xx_pcmcia_attach(void *opaque
, PCMCIACardState
*card
)
198 PXA2xxPCMCIAState
*s
= (PXA2xxPCMCIAState
*) opaque
;
199 PCMCIACardClass
*pcc
;
201 if (s
->slot
.attached
) {
206 qemu_irq_raise(s
->cd_irq
);
210 pcc
= PCMCIA_CARD_GET_CLASS(s
->card
);
212 s
->slot
.attached
= true;
213 s
->card
->slot
= &s
->slot
;
214 pcc
->attach(s
->card
);
219 /* Eject card from the slot */
220 int pxa2xx_pcmcia_detach(void *opaque
)
222 PXA2xxPCMCIAState
*s
= (PXA2xxPCMCIAState
*) opaque
;
223 PCMCIACardClass
*pcc
;
225 if (!s
->slot
.attached
) {
229 pcc
= PCMCIA_CARD_GET_CLASS(s
->card
);
230 pcc
->detach(s
->card
);
231 s
->card
->slot
= NULL
;
234 s
->slot
.attached
= false;
237 qemu_irq_lower(s
->irq
);
240 qemu_irq_lower(s
->cd_irq
);
246 /* Who to notify on card events */
247 void pxa2xx_pcmcia_set_irq_cb(void *opaque
, qemu_irq irq
, qemu_irq cd_irq
)
249 PXA2xxPCMCIAState
*s
= (PXA2xxPCMCIAState
*) opaque
;
254 static const TypeInfo pxa2xx_pcmcia_type_info
= {
255 .name
= TYPE_PXA2XX_PCMCIA
,
256 .parent
= TYPE_SYS_BUS_DEVICE
,
257 .instance_size
= sizeof(PXA2xxPCMCIAState
),
258 .instance_init
= pxa2xx_pcmcia_initfn
,
261 static void pxa2xx_pcmcia_register_types(void)
263 type_register_static(&pxa2xx_pcmcia_type_info
);
266 type_init(pxa2xx_pcmcia_register_types
)